slang_rs_export_type.h revision 2b8fb64be3047df940a219872b331eb11de2758d
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 _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_ // NOLINT 18#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_ 19 20#include <list> 21#include <set> 22#include <string> 23 24#include "clang/AST/Decl.h" 25#include "clang/AST/Type.h" 26 27#include "llvm/ADT/SmallPtrSet.h" 28#include "llvm/ADT/StringMap.h" 29#include "llvm/ADT/StringRef.h" 30 31#include "llvm/Support/ManagedStatic.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 53union RSType; 54 55namespace llvm { 56 class Type; 57} // namespace llvm 58 59namespace slang { 60 61 class RSContext; 62 63typedef struct { 64 const char * rs_type; 65 const char * rs_short_type; 66 uint32_t size_in_bits; 67 const char * c_name; 68 const char * java_name; 69 const char * rs_c_vector_prefix; 70 const char * rs_java_vector_prefix; 71 bool java_promotion; 72} RSReflectionType; 73 74class RSExportType : public RSExportable { 75 friend class RSExportElement; 76 public: 77 typedef enum { 78 ExportClassPrimitive, 79 ExportClassPointer, 80 ExportClassVector, 81 ExportClassMatrix, 82 ExportClassConstantArray, 83 ExportClassRecord 84 } ExportClass; 85 86 private: 87 ExportClass mClass; 88 std::string mName; 89 90 // Cache the result after calling convertToLLVMType() at the first time 91 mutable llvm::Type *mLLVMType; 92 // Cache the result after calling convertToSpecType() at the first time 93 mutable union RSType *mSpecType; 94 95 protected: 96 RSExportType(RSContext *Context, 97 ExportClass Class, 98 const llvm::StringRef &Name); 99 100 // Let's make it private since there're some prerequisites to call this 101 // function. 102 // 103 // @T was normalized by calling RSExportType::NormalizeType(). 104 // @TypeName was retrieve from RSExportType::GetTypeName() before calling 105 // this. 106 // 107 static RSExportType *Create(RSContext *Context, 108 const clang::Type *T, 109 const llvm::StringRef &TypeName); 110 111 static llvm::StringRef GetTypeName(const clang::Type *T); 112 113 // This function convert the RSExportType to LLVM type. Actually, it should be 114 // "convert Clang type to LLVM type." However, clang doesn't make this API 115 // (lib/CodeGen/CodeGenTypes.h) public, we need to do by ourselves. 116 // 117 // Once we can get LLVM type, we can use LLVM to get alignment information, 118 // allocation size of a given type and structure layout that LLVM used 119 // (all of these information are target dependent) without dealing with these 120 // by ourselves. 121 virtual llvm::Type *convertToLLVMType() const = 0; 122 // Record type may recursively reference its type definition. We need a 123 // temporary type setup before the type construction gets done. 124 inline void setAbstractLLVMType(llvm::Type *LLVMType) const { 125 mLLVMType = LLVMType; 126 } 127 128 virtual union RSType *convertToSpecType() const = 0; 129 inline void setSpecTypeTemporarily(union RSType *SpecType) const { 130 mSpecType = SpecType; 131 } 132 133 virtual ~RSExportType(); 134 135 public: 136 // This function additionally verifies that the Type T is exportable. 137 // If it is not, this function returns false. Otherwise it returns true. 138 static bool NormalizeType(const clang::Type *&T, 139 llvm::StringRef &TypeName, 140 clang::DiagnosticsEngine *Diags, 141 const clang::VarDecl *VD); 142 143 // This function ensures that the VarDecl can be properly handled by RS. 144 // If it cannot, this function returns false. Otherwise it returns true. 145 static bool ValidateVarDecl(clang::VarDecl *VD); 146 147 // @T may not be normalized 148 static RSExportType *Create(RSContext *Context, const clang::Type *T); 149 static RSExportType *CreateFromDecl(RSContext *Context, 150 const clang::VarDecl *VD); 151 152 static const clang::Type *GetTypeOfDecl(const clang::DeclaratorDecl *DD); 153 154 inline ExportClass getClass() const { return mClass; } 155 156 inline llvm::Type *getLLVMType() const { 157 if (mLLVMType == NULL) 158 mLLVMType = convertToLLVMType(); 159 return mLLVMType; 160 } 161 162 inline const union RSType *getSpecType() const { 163 if (mSpecType == NULL) 164 mSpecType = convertToSpecType(); 165 return mSpecType; 166 } 167 168 // Return the number of bits necessary to hold the specified RSExportType 169 static size_t GetTypeStoreSize(const RSExportType *ET); 170 171 // The size of allocation of specified RSExportType (alignment considered) 172 static size_t GetTypeAllocSize(const RSExportType *ET); 173 174 inline const std::string &getName() const { return mName; } 175 176 virtual bool keep(); 177 virtual bool equals(const RSExportable *E) const; 178}; // RSExportType 179 180// Primitive types 181class RSExportPrimitiveType : public RSExportType { 182 friend class RSExportType; 183 friend class RSExportElement; 184 public: 185 // From graphics/java/android/renderscript/Element.java: Element.DataType 186 typedef enum { 187 DataTypeIsStruct = -2, 188 DataTypeUnknown = -1, 189 190#define ENUM_PRIMITIVE_DATA_TYPE_RANGE(begin_type, end_type) \ 191 FirstPrimitiveType = DataType ## begin_type, \ 192 LastPrimitiveType = DataType ## end_type, 193 194#define ENUM_RS_MATRIX_DATA_TYPE_RANGE(begin_type, end_type) \ 195 FirstRSMatrixType = DataType ## begin_type, \ 196 LastRSMatrixType = DataType ## end_type, 197 198#define ENUM_RS_OBJECT_DATA_TYPE_RANGE(begin_type, end_type) \ 199 FirstRSObjectType = DataType ## begin_type, \ 200 LastRSObjectType = DataType ## end_type, 201 202#define ENUM_RS_DATA_TYPE(type, cname, bits) \ 203 DataType ## type, 204 205#include "RSDataTypeEnums.inc" 206 207 DataTypeMax 208 } DataType; 209 210 private: 211 // NOTE: There's no any instance of RSExportPrimitiveType which mType 212 // is of the value DataTypeRSMatrix*. DataTypeRSMatrix* enumeration here is 213 // only for RSExportPrimitiveType::GetRSObjectType to *recognize* the struct 214 // rs_matrix{2x2, 3x3, 4x4}. These matrix type are represented as 215 // RSExportMatrixType. 216 DataType mType; 217 bool mNormalized; 218 219 typedef llvm::StringMap<DataType> RSSpecificTypeMapTy; 220 static llvm::ManagedStatic<RSSpecificTypeMapTy> RSSpecificTypeMap; 221 222 static llvm::Type *RSObjectLLVMType; 223 224 static const size_t SizeOfDataTypeInBits[]; 225 // @T was normalized by calling RSExportType::NormalizeType() before calling 226 // this. 227 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 228 // this 229 static RSExportPrimitiveType *Create(RSContext *Context, 230 const clang::Type *T, 231 const llvm::StringRef &TypeName, 232 bool Normalized = false); 233 234 protected: 235 RSExportPrimitiveType(RSContext *Context, 236 // for derived class to set their type class 237 ExportClass Class, 238 const llvm::StringRef &Name, 239 DataType DT, 240 bool Normalized) 241 : RSExportType(Context, Class, Name), 242 mType(DT), 243 mNormalized(Normalized) { 244 return; 245 } 246 247 virtual llvm::Type *convertToLLVMType() const; 248 virtual union RSType *convertToSpecType() const; 249 250 static DataType GetDataType(RSContext *Context, const clang::Type *T); 251 252 public: 253 // T is normalized by calling RSExportType::NormalizeType() before 254 // calling this 255 static bool IsPrimitiveType(const clang::Type *T); 256 257 // @T may not be normalized 258 static RSExportPrimitiveType *Create(RSContext *Context, 259 const clang::Type *T); 260 261 static DataType GetRSSpecificType(const llvm::StringRef &TypeName); 262 static DataType GetRSSpecificType(const clang::Type *T); 263 264 static bool IsRSMatrixType(DataType DT); 265 static bool IsRSObjectType(DataType DT); 266 static bool IsRSObjectType(const clang::Type *T) { 267 return IsRSObjectType(GetRSSpecificType(T)); 268 } 269 270 // Determines whether T is [an array of] struct that contains at least one 271 // RS object type within it. 272 static bool IsStructureTypeWithRSObject(const clang::Type *T); 273 274 static size_t GetSizeInBits(const RSExportPrimitiveType *EPT); 275 276 inline DataType getType() const { return mType; } 277 inline bool isRSObjectType() const { 278 return ((mType >= FirstRSObjectType) && (mType <= LastRSObjectType)); 279 } 280 281 virtual bool equals(const RSExportable *E) const; 282 283 static RSReflectionType *getRSReflectionType(DataType DT); 284 static RSReflectionType *getRSReflectionType( 285 const RSExportPrimitiveType *EPT) { 286 return getRSReflectionType(EPT->getType()); 287 } 288}; // RSExportPrimitiveType 289 290 291class RSExportPointerType : public RSExportType { 292 friend class RSExportType; 293 friend class RSExportFunc; 294 private: 295 const RSExportType *mPointeeType; 296 297 RSExportPointerType(RSContext *Context, 298 const llvm::StringRef &Name, 299 const RSExportType *PointeeType) 300 : RSExportType(Context, ExportClassPointer, Name), 301 mPointeeType(PointeeType) { 302 return; 303 } 304 305 // @PT was normalized by calling RSExportType::NormalizeType() before calling 306 // this. 307 static RSExportPointerType *Create(RSContext *Context, 308 const clang::PointerType *PT, 309 const llvm::StringRef &TypeName); 310 311 virtual llvm::Type *convertToLLVMType() const; 312 virtual union RSType *convertToSpecType() const; 313 314 public: 315 virtual bool keep(); 316 317 inline const RSExportType *getPointeeType() const { return mPointeeType; } 318 319 virtual bool equals(const RSExportable *E) const; 320}; // RSExportPointerType 321 322 323class RSExportVectorType : public RSExportPrimitiveType { 324 friend class RSExportType; 325 friend class RSExportElement; 326 private: 327 unsigned mNumElement; // number of element 328 329 RSExportVectorType(RSContext *Context, 330 const llvm::StringRef &Name, 331 DataType DT, 332 bool Normalized, 333 unsigned NumElement) 334 : RSExportPrimitiveType(Context, ExportClassVector, Name, 335 DT, Normalized), 336 mNumElement(NumElement) { 337 return; 338 } 339 340 // @EVT was normalized by calling RSExportType::NormalizeType() before 341 // calling this. 342 static RSExportVectorType *Create(RSContext *Context, 343 const clang::ExtVectorType *EVT, 344 const llvm::StringRef &TypeName, 345 bool Normalized = false); 346 347 virtual llvm::Type *convertToLLVMType() const; 348 virtual union RSType *convertToSpecType() const; 349 350 public: 351 static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT); 352 353 inline unsigned getNumElement() const { return mNumElement; } 354 355 virtual bool equals(const RSExportable *E) const; 356}; 357 358// Only *square* *float* matrix is supported by now. 359// 360// struct rs_matrix{2x2,3x3,4x4, ..., NxN} should be defined as the following 361// form *exactly*: 362// typedef struct { 363// float m[{NxN}]; 364// } rs_matrixNxN; 365// 366// where mDim will be N. 367class RSExportMatrixType : public RSExportType { 368 friend class RSExportType; 369 private: 370 unsigned mDim; // dimension 371 372 RSExportMatrixType(RSContext *Context, 373 const llvm::StringRef &Name, 374 unsigned Dim) 375 : RSExportType(Context, ExportClassMatrix, Name), 376 mDim(Dim) { 377 return; 378 } 379 380 virtual llvm::Type *convertToLLVMType() const; 381 virtual union RSType *convertToSpecType() const; 382 383 public: 384 // @RT was normalized by calling RSExportType::NormalizeType() before 385 // calling this. 386 static RSExportMatrixType *Create(RSContext *Context, 387 const clang::RecordType *RT, 388 const llvm::StringRef &TypeName, 389 unsigned Dim); 390 391 inline unsigned getDim() const { return mDim; } 392 393 virtual bool equals(const RSExportable *E) const; 394}; 395 396class RSExportConstantArrayType : public RSExportType { 397 friend class RSExportType; 398 private: 399 const RSExportType *mElementType; // Array element type 400 unsigned mSize; // Array size 401 402 RSExportConstantArrayType(RSContext *Context, 403 const RSExportType *ElementType, 404 unsigned Size) 405 : RSExportType(Context, 406 ExportClassConstantArray, 407 DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE), 408 mElementType(ElementType), 409 mSize(Size) { 410 return; 411 } 412 413 // @CAT was normalized by calling RSExportType::NormalizeType() before 414 // calling this. 415 static RSExportConstantArrayType *Create(RSContext *Context, 416 const clang::ConstantArrayType *CAT); 417 418 virtual llvm::Type *convertToLLVMType() const; 419 virtual union RSType *convertToSpecType() const; 420 421 public: 422 inline unsigned getSize() const { return mSize; } 423 inline const RSExportType *getElementType() const { return mElementType; } 424 425 virtual bool keep(); 426 virtual bool equals(const RSExportable *E) const; 427}; 428 429class RSExportRecordType : public RSExportType { 430 friend class RSExportType; 431 public: 432 class Field { 433 private: 434 const RSExportType *mType; 435 // Field name 436 std::string mName; 437 // Link to the struct that contain this field 438 const RSExportRecordType *mParent; 439 // Offset in the container 440 size_t mOffset; 441 442 public: 443 Field(const RSExportType *T, 444 const llvm::StringRef &Name, 445 const RSExportRecordType *Parent, 446 size_t Offset) 447 : mType(T), 448 mName(Name.data(), Name.size()), 449 mParent(Parent), 450 mOffset(Offset) { 451 return; 452 } 453 454 inline const RSExportRecordType *getParent() const { return mParent; } 455 inline const RSExportType *getType() const { return mType; } 456 inline const std::string &getName() const { return mName; } 457 inline size_t getOffsetInParent() const { return mOffset; } 458 }; 459 460 typedef std::list<const Field*>::const_iterator const_field_iterator; 461 462 inline const_field_iterator fields_begin() const { 463 return this->mFields.begin(); 464 } 465 inline const_field_iterator fields_end() const { 466 return this->mFields.end(); 467 } 468 469 private: 470 std::list<const Field*> mFields; 471 bool mIsPacked; 472 // Artificial export struct type is not exported by user (and thus it won't 473 // get reflected) 474 bool mIsArtificial; 475 size_t mAllocSize; 476 477 RSExportRecordType(RSContext *Context, 478 const llvm::StringRef &Name, 479 bool IsPacked, 480 bool IsArtificial, 481 size_t AllocSize) 482 : RSExportType(Context, ExportClassRecord, Name), 483 mIsPacked(IsPacked), 484 mIsArtificial(IsArtificial), 485 mAllocSize(AllocSize) { 486 return; 487 } 488 489 // @RT was normalized by calling RSExportType::NormalizeType() before calling 490 // this. 491 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 492 // this. 493 static RSExportRecordType *Create(RSContext *Context, 494 const clang::RecordType *RT, 495 const llvm::StringRef &TypeName, 496 bool mIsArtificial = false); 497 498 virtual llvm::Type *convertToLLVMType() const; 499 virtual union RSType *convertToSpecType() const; 500 501 public: 502 inline const std::list<const Field*>& getFields() const { return mFields; } 503 inline bool isPacked() const { return mIsPacked; } 504 inline bool isArtificial() const { return mIsArtificial; } 505 inline size_t getAllocSize() const { return mAllocSize; } 506 507 virtual bool keep(); 508 virtual bool equals(const RSExportable *E) const; 509 510 ~RSExportRecordType() { 511 for (std::list<const Field*>::iterator I = mFields.begin(), 512 E = mFields.end(); 513 I != E; 514 I++) 515 if (*I != NULL) 516 delete *I; 517 return; 518 } 519}; // RSExportRecordType 520 521} // namespace slang 522 523#endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_ NOLINT 524