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