slang_rs_export_type.h revision c95381a2c3b6e9117901eef0687e861e4d533bfe
1/* 2 * Copyright 2010-2012, 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#include <sstream> 24 25#include "clang/AST/Decl.h" 26#include "clang/AST/Type.h" 27 28#include "llvm/ADT/SmallPtrSet.h" 29#include "llvm/ADT/StringMap.h" 30#include "llvm/ADT/StringRef.h" 31 32#include "llvm/Support/ManagedStatic.h" 33 34#include "slang_rs_exportable.h" 35 36#define GET_CANONICAL_TYPE(T) \ 37 (((T) == NULL) ? NULL : (T)->getCanonicalTypeInternal().getTypePtr()) 38#define UNSAFE_CAST_TYPE(TT, T) \ 39 static_cast<TT*>(T->getCanonicalTypeInternal().getTypePtr()) 40#define GET_EXT_VECTOR_ELEMENT_TYPE(T) \ 41 (((T) == NULL) ? NULL : \ 42 GET_CANONICAL_TYPE((T)->getElementType().getTypePtr())) 43#define GET_POINTEE_TYPE(T) \ 44 (((T) == NULL) ? NULL : \ 45 GET_CANONICAL_TYPE((T)->getPointeeType().getTypePtr())) 46#define GET_CONSTANT_ARRAY_ELEMENT_TYPE(T) \ 47 (((T) == NULL) ? NULL : \ 48 GET_CANONICAL_TYPE((T)->getElementType().getTypePtr())) 49#define DUMMY_RS_TYPE_NAME_PREFIX "<" 50#define DUMMY_RS_TYPE_NAME_POSTFIX ">" 51#define DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE \ 52 DUMMY_RS_TYPE_NAME_PREFIX "ConstantArray" DUMMY_RS_TYPE_NAME_POSTFIX 53 54namespace llvm { 55 class Type; 56} // namespace llvm 57 58namespace slang { 59 60class RSContext; 61 62// Broad grouping of the data types 63enum DataTypeCategory { 64 PrimitiveDataType, 65 MatrixDataType, 66 ObjectDataType 67}; 68 69// From graphics/java/android/renderscript/Element.java: Element.DataType 70/* NOTE: The values of the enums are found compiled in the bit code (i.e. as 71 * values, not symbolic. When adding new types, you must add them to the end. 72 * If removing types, you can't re-use the integer value. 73 * 74 * TODO: but if you do this, you won't be able to keep using First* & Last* 75 * for validation. 76 * 77 * IMPORTANT: This enum should correspond one-for-one to the entries found in the 78 * gReflectionsTypes table (except for the two negative numbers). Don't edit one without 79 * the other. 80 */ 81enum DataType { 82 DataTypeIsStruct = -2, 83 DataTypeUnknown = -1, 84 85 DataTypeFloat16 = 0, 86 DataTypeFloat32 = 1, 87 DataTypeFloat64 = 2, 88 DataTypeSigned8 = 3, 89 DataTypeSigned16 = 4, 90 DataTypeSigned32 = 5, 91 DataTypeSigned64 = 6, 92 DataTypeUnsigned8 = 7, 93 DataTypeUnsigned16 = 8, 94 DataTypeUnsigned32 = 9, 95 DataTypeUnsigned64 = 10, 96 DataTypeBoolean = 11, 97 DataTypeUnsigned565 = 12, 98 DataTypeUnsigned5551 = 13, 99 DataTypeUnsigned4444 = 14, 100 101 DataTypeRSMatrix2x2 = 15, 102 DataTypeRSMatrix3x3 = 16, 103 DataTypeRSMatrix4x4 = 17, 104 105 DataTypeRSElement = 18, 106 DataTypeRSType = 19, 107 DataTypeRSAllocation = 20, 108 DataTypeRSSampler = 21, 109 DataTypeRSScript = 22, 110 DataTypeRSMesh = 23, 111 DataTypeRSPath = 24, 112 DataTypeRSProgramFragment = 25, 113 DataTypeRSProgramVertex = 26, 114 DataTypeRSProgramRaster = 27, 115 DataTypeRSProgramStore = 28, 116 DataTypeRSFont = 29, 117 118 // This should always be last and correspond to the size of the gReflectionTypes table. 119 DataTypeMax 120}; 121 122typedef struct { 123 DataTypeCategory category; 124 const char * rs_type; 125 const char * rs_short_type; 126 uint32_t size_in_bits; 127 const char * c_name; 128 const char * java_name; 129 const char * rs_c_vector_prefix; 130 const char * rs_java_vector_prefix; 131 bool java_promotion; 132} RSReflectionType; 133 134 135typedef struct RSReflectionTypeData_rec { 136 const RSReflectionType *type; 137 uint32_t vecSize; 138 bool isPointer; 139 uint32_t arraySize; 140 141 // Subelements 142 //std::vector<const struct RSReflectionTypeData_rec *> fields; 143 //std::vector< std::string > fieldNames; 144 //std::vector< uint32_t> fieldOffsetBytes; 145} RSReflectionTypeData; 146 147 148class RSExportType : public RSExportable { 149 friend class RSExportElement; 150 public: 151 typedef enum { 152 ExportClassPrimitive, 153 ExportClassPointer, 154 ExportClassVector, 155 ExportClassMatrix, 156 ExportClassConstantArray, 157 ExportClassRecord 158 } ExportClass; 159 160 void convertToRTD(RSReflectionTypeData *rtd) const; 161 162 private: 163 ExportClass mClass; 164 std::string mName; 165 166 // Cache the result after calling convertToLLVMType() at the first time 167 mutable llvm::Type *mLLVMType; 168 169 protected: 170 RSExportType(RSContext *Context, 171 ExportClass Class, 172 const llvm::StringRef &Name); 173 174 // Let's make it private since there're some prerequisites to call this 175 // function. 176 // 177 // @T was normalized by calling RSExportType::NormalizeType(). 178 // @TypeName was retrieve from RSExportType::GetTypeName() before calling 179 // this. 180 // 181 static RSExportType *Create(RSContext *Context, 182 const clang::Type *T, 183 const llvm::StringRef &TypeName); 184 185 static llvm::StringRef GetTypeName(const clang::Type *T); 186 187 // This function convert the RSExportType to LLVM type. Actually, it should be 188 // "convert Clang type to LLVM type." However, clang doesn't make this API 189 // (lib/CodeGen/CodeGenTypes.h) public, we need to do by ourselves. 190 // 191 // Once we can get LLVM type, we can use LLVM to get alignment information, 192 // allocation size of a given type and structure layout that LLVM used 193 // (all of these information are target dependent) without dealing with these 194 // by ourselves. 195 virtual llvm::Type *convertToLLVMType() const = 0; 196 // Record type may recursively reference its type definition. We need a 197 // temporary type setup before the type construction gets done. 198 inline void setAbstractLLVMType(llvm::Type *LLVMType) const { 199 mLLVMType = LLVMType; 200 } 201 202 virtual ~RSExportType(); 203 204 public: 205 // This function additionally verifies that the Type T is exportable. 206 // If it is not, this function returns false. Otherwise it returns true. 207 static bool NormalizeType(const clang::Type *&T, 208 llvm::StringRef &TypeName, 209 RSContext *Context, 210 const clang::VarDecl *VD); 211 212 // This function checks whether the specified type can be handled by RS/FS. 213 // If it cannot, this function returns false. Otherwise it returns true. 214 // Filterscript has additional restrictions on supported types. 215 static bool ValidateType(slang::RSContext *Context, clang::ASTContext &C, 216 clang::QualType QT, clang::NamedDecl *ND, 217 clang::SourceLocation Loc, unsigned int TargetAPI, 218 bool IsFilterscript); 219 220 // This function ensures that the VarDecl can be properly handled by RS. 221 // If it cannot, this function returns false. Otherwise it returns true. 222 // Filterscript has additional restrictions on supported types. 223 static bool ValidateVarDecl(slang::RSContext *Context, clang::VarDecl *VD, 224 unsigned int TargetAPI, bool IsFilterscript); 225 226 // @T may not be normalized 227 static RSExportType *Create(RSContext *Context, const clang::Type *T); 228 static RSExportType *CreateFromDecl(RSContext *Context, 229 const clang::VarDecl *VD); 230 231 static const clang::Type *GetTypeOfDecl(const clang::DeclaratorDecl *DD); 232 233 inline ExportClass getClass() const { return mClass; } 234 235 virtual unsigned getSize() const { return 1; } 236 237 inline llvm::Type *getLLVMType() const { 238 if (mLLVMType == NULL) 239 mLLVMType = convertToLLVMType(); 240 return mLLVMType; 241 } 242 243 // Return the maximum number of bytes that may be written when this type is stored. 244 virtual size_t getStoreSize() const; 245 246 // Return the distance in bytes between successive elements of this type; it includes padding. 247 virtual size_t getAllocSize() const; 248 249 inline const std::string &getName() const { return mName; } 250 251 virtual std::string getElementName() const { 252 // Base case is actually an invalid C/Java identifier. 253 return "@@INVALID@@"; 254 } 255 256 virtual bool keep(); 257 virtual bool equals(const RSExportable *E) const; 258}; // RSExportType 259 260// Primitive types 261class RSExportPrimitiveType : public RSExportType { 262 friend class RSExportType; 263 friend class RSExportElement; 264 private: 265 // NOTE: There's no any instance of RSExportPrimitiveType which mType 266 // is of the value DataTypeRSMatrix*. DataTypeRSMatrix* enumeration here is 267 // only for RSExportPrimitiveType::GetRSObjectType to *recognize* the struct 268 // rs_matrix{2x2, 3x3, 4x4}. These matrix type are represented as 269 // RSExportMatrixType. 270 DataType mType; 271 bool mNormalized; 272 273 typedef llvm::StringMap<DataType> RSSpecificTypeMapTy; 274 static llvm::ManagedStatic<RSSpecificTypeMapTy> RSSpecificTypeMap; 275 276 static llvm::Type *RSObjectLLVMType; 277 278 static const size_t SizeOfDataTypeInBits[]; 279 // @T was normalized by calling RSExportType::NormalizeType() before calling 280 // this. 281 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 282 // this 283 static RSExportPrimitiveType *Create(RSContext *Context, 284 const clang::Type *T, 285 const llvm::StringRef &TypeName, 286 bool Normalized = false); 287 288 protected: 289 RSExportPrimitiveType(RSContext *Context, 290 // for derived class to set their type class 291 ExportClass Class, 292 const llvm::StringRef &Name, 293 DataType DT, 294 bool Normalized) 295 : RSExportType(Context, Class, Name), 296 mType(DT), 297 mNormalized(Normalized) { 298 return; 299 } 300 301 virtual llvm::Type *convertToLLVMType() const; 302 303 static DataType GetDataType(RSContext *Context, const clang::Type *T); 304 305 public: 306 // T is normalized by calling RSExportType::NormalizeType() before 307 // calling this 308 static bool IsPrimitiveType(const clang::Type *T); 309 310 // @T may not be normalized 311 static RSExportPrimitiveType *Create(RSContext *Context, 312 const clang::Type *T); 313 314 static DataType GetRSSpecificType(const llvm::StringRef &TypeName); 315 static DataType GetRSSpecificType(const clang::Type *T); 316 317 static bool IsRSMatrixType(DataType DT); 318 static bool IsRSObjectType(DataType DT); 319 static bool IsRSObjectType(const clang::Type *T) { 320 return IsRSObjectType(GetRSSpecificType(T)); 321 } 322 323 // Determines whether T is [an array of] struct that contains at least one 324 // RS object type within it. 325 static bool IsStructureTypeWithRSObject(const clang::Type *T); 326 327 static size_t GetSizeInBits(const RSExportPrimitiveType *EPT); 328 329 inline DataType getType() const { return mType; } 330 inline bool isRSObjectType() const { 331 return IsRSObjectType(mType); 332 } 333 334 virtual bool equals(const RSExportable *E) const; 335 336 static RSReflectionType *getRSReflectionType(DataType DT); 337 static RSReflectionType *getRSReflectionType( 338 const RSExportPrimitiveType *EPT) { 339 return getRSReflectionType(EPT->getType()); 340 } 341 342 virtual unsigned getSize() const { return (GetSizeInBits(this) >> 3); } 343 344 std::string getElementName() const { 345 return getRSReflectionType(this)->rs_short_type; 346 } 347}; // RSExportPrimitiveType 348 349 350class RSExportPointerType : public RSExportType { 351 friend class RSExportType; 352 friend class RSExportFunc; 353 private: 354 const RSExportType *mPointeeType; 355 356 RSExportPointerType(RSContext *Context, 357 const llvm::StringRef &Name, 358 const RSExportType *PointeeType) 359 : RSExportType(Context, ExportClassPointer, Name), 360 mPointeeType(PointeeType) { 361 return; 362 } 363 364 // @PT was normalized by calling RSExportType::NormalizeType() before calling 365 // this. 366 static RSExportPointerType *Create(RSContext *Context, 367 const clang::PointerType *PT, 368 const llvm::StringRef &TypeName); 369 370 virtual llvm::Type *convertToLLVMType() const; 371 372 public: 373 virtual bool keep(); 374 375 inline const RSExportType *getPointeeType() const { return mPointeeType; } 376 377 virtual bool equals(const RSExportable *E) const; 378}; // RSExportPointerType 379 380 381class RSExportVectorType : public RSExportPrimitiveType { 382 friend class RSExportType; 383 friend class RSExportElement; 384 private: 385 unsigned mNumElement; // number of element 386 387 RSExportVectorType(RSContext *Context, 388 const llvm::StringRef &Name, 389 DataType DT, 390 bool Normalized, 391 unsigned NumElement) 392 : RSExportPrimitiveType(Context, ExportClassVector, Name, 393 DT, Normalized), 394 mNumElement(NumElement) { 395 return; 396 } 397 398 // @EVT was normalized by calling RSExportType::NormalizeType() before 399 // calling this. 400 static RSExportVectorType *Create(RSContext *Context, 401 const clang::ExtVectorType *EVT, 402 const llvm::StringRef &TypeName, 403 bool Normalized = false); 404 405 virtual llvm::Type *convertToLLVMType() const; 406 407 public: 408 static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT); 409 410 inline unsigned getNumElement() const { return mNumElement; } 411 412 std::string getElementName() const { 413 std::stringstream Name; 414 Name << RSExportPrimitiveType::getRSReflectionType(this)->rs_short_type 415 << "_" << getNumElement(); 416 return Name.str(); 417 } 418 419 virtual bool equals(const RSExportable *E) const; 420}; 421 422// Only *square* *float* matrix is supported by now. 423// 424// struct rs_matrix{2x2,3x3,4x4, ..., NxN} should be defined as the following 425// form *exactly*: 426// typedef struct { 427// float m[{NxN}]; 428// } rs_matrixNxN; 429// 430// where mDim will be N. 431class RSExportMatrixType : public RSExportType { 432 friend class RSExportType; 433 private: 434 unsigned mDim; // dimension 435 436 RSExportMatrixType(RSContext *Context, 437 const llvm::StringRef &Name, 438 unsigned Dim) 439 : RSExportType(Context, ExportClassMatrix, Name), 440 mDim(Dim) { 441 return; 442 } 443 444 virtual llvm::Type *convertToLLVMType() const; 445 446 public: 447 // @RT was normalized by calling RSExportType::NormalizeType() before 448 // calling this. 449 static RSExportMatrixType *Create(RSContext *Context, 450 const clang::RecordType *RT, 451 const llvm::StringRef &TypeName, 452 unsigned Dim); 453 454 inline unsigned getDim() const { return mDim; } 455 456 virtual bool equals(const RSExportable *E) const; 457}; 458 459class RSExportConstantArrayType : public RSExportType { 460 friend class RSExportType; 461 private: 462 const RSExportType *mElementType; // Array element type 463 unsigned mSize; // Array size 464 465 RSExportConstantArrayType(RSContext *Context, 466 const RSExportType *ElementType, 467 unsigned Size) 468 : RSExportType(Context, 469 ExportClassConstantArray, 470 DUMMY_TYPE_NAME_FOR_RS_CONSTANT_ARRAY_TYPE), 471 mElementType(ElementType), 472 mSize(Size) { 473 return; 474 } 475 476 // @CAT was normalized by calling RSExportType::NormalizeType() before 477 // calling this. 478 static RSExportConstantArrayType *Create(RSContext *Context, 479 const clang::ConstantArrayType *CAT); 480 481 virtual llvm::Type *convertToLLVMType() const; 482 483 public: 484 virtual unsigned getSize() const { return mSize; } 485 inline const RSExportType *getElementType() const { return mElementType; } 486 487 std::string getElementName() const { 488 return mElementType->getElementName(); 489 } 490 491 virtual bool keep(); 492 virtual bool equals(const RSExportable *E) const; 493}; 494 495class RSExportRecordType : public RSExportType { 496 friend class RSExportType; 497 public: 498 class Field { 499 private: 500 const RSExportType *mType; 501 // Field name 502 std::string mName; 503 // Link to the struct that contain this field 504 const RSExportRecordType *mParent; 505 // Offset in the container 506 size_t mOffset; 507 508 public: 509 Field(const RSExportType *T, 510 const llvm::StringRef &Name, 511 const RSExportRecordType *Parent, 512 size_t Offset) 513 : mType(T), 514 mName(Name.data(), Name.size()), 515 mParent(Parent), 516 mOffset(Offset) { 517 return; 518 } 519 520 inline const RSExportRecordType *getParent() const { return mParent; } 521 inline const RSExportType *getType() const { return mType; } 522 inline const std::string &getName() const { return mName; } 523 inline size_t getOffsetInParent() const { return mOffset; } 524 }; 525 526 typedef std::list<const Field*>::const_iterator const_field_iterator; 527 528 inline const_field_iterator fields_begin() const { 529 return this->mFields.begin(); 530 } 531 inline const_field_iterator fields_end() const { 532 return this->mFields.end(); 533 } 534 535 private: 536 std::list<const Field*> mFields; 537 bool mIsPacked; 538 // Artificial export struct type is not exported by user (and thus it won't 539 // get reflected) 540 bool mIsArtificial; 541 size_t mStoreSize; 542 size_t mAllocSize; 543 544 RSExportRecordType(RSContext *Context, 545 const llvm::StringRef &Name, 546 bool IsPacked, 547 bool IsArtificial, 548 size_t StoreSize, 549 size_t AllocSize) 550 : RSExportType(Context, ExportClassRecord, Name), 551 mIsPacked(IsPacked), 552 mIsArtificial(IsArtificial), 553 mStoreSize(StoreSize), 554 mAllocSize(AllocSize) { 555 return; 556 } 557 558 // @RT was normalized by calling RSExportType::NormalizeType() before calling 559 // this. 560 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 561 // this. 562 static RSExportRecordType *Create(RSContext *Context, 563 const clang::RecordType *RT, 564 const llvm::StringRef &TypeName, 565 bool mIsArtificial = false); 566 567 virtual llvm::Type *convertToLLVMType() const; 568 569 public: 570 inline const std::list<const Field*>& getFields() const { return mFields; } 571 inline bool isPacked() const { return mIsPacked; } 572 inline bool isArtificial() const { return mIsArtificial; } 573 virtual size_t getStoreSize() const { return mStoreSize; } 574 virtual size_t getAllocSize() const { return mAllocSize; } 575 576 virtual std::string getElementName() const { 577 return "ScriptField_" + getName(); 578 } 579 580 virtual bool keep(); 581 virtual bool equals(const RSExportable *E) const; 582 583 ~RSExportRecordType() { 584 for (std::list<const Field*>::iterator I = mFields.begin(), 585 E = mFields.end(); 586 I != E; 587 I++) 588 if (*I != NULL) 589 delete *I; 590 return; 591 } 592}; // RSExportRecordType 593 594} // namespace slang 595 596#endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_ NOLINT 597