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