slang_rs_export_type.h revision 657d20afa621219c1eed72178d1325fd4409f458
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; // number of elements; one if not a vector 166 bool isPointer; 167 uint32_t arraySize; // number of elements; zero if not an array 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 inline llvm::Type *getLLVMType() const { 270 if (mLLVMType == nullptr) 271 mLLVMType = convertToLLVMType(); 272 return mLLVMType; 273 } 274 275 // Return the maximum number of bytes that may be written when this type is stored. 276 virtual size_t getStoreSize() const; 277 278 // Return the distance in bytes between successive elements of this type; it includes padding. 279 virtual size_t getAllocSize() const; 280 281 inline const std::string &getName() const { return mName; } 282 283 virtual std::string getElementName() const { 284 // Base case is actually an invalid C/Java identifier. 285 return "@@INVALID@@"; 286 } 287 288 virtual bool keep(); 289 virtual bool equals(const RSExportable *E) const; 290}; // RSExportType 291 292// Primitive types 293class RSExportPrimitiveType : public RSExportType { 294 friend class RSExportType; 295 friend class RSExportElement; 296 private: 297 DataType mType; 298 bool mNormalized; 299 300 typedef llvm::StringMap<DataType> RSSpecificTypeMapTy; 301 static llvm::ManagedStatic<RSSpecificTypeMapTy> RSSpecificTypeMap; 302 303 static const size_t SizeOfDataTypeInBits[]; 304 // @T was normalized by calling RSExportType::NormalizeType() before calling 305 // this. 306 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 307 // this 308 static RSExportPrimitiveType *Create(RSContext *Context, 309 const clang::Type *T, 310 const llvm::StringRef &TypeName, 311 bool Normalized = false); 312 313 protected: 314 RSExportPrimitiveType(RSContext *Context, 315 // for derived class to set their type class 316 ExportClass Class, 317 const llvm::StringRef &Name, 318 DataType DT, 319 bool Normalized) 320 : RSExportType(Context, Class, Name), 321 mType(DT), 322 mNormalized(Normalized) { 323 } 324 325 virtual llvm::Type *convertToLLVMType() const; 326 327 static DataType GetDataType(RSContext *Context, const clang::Type *T); 328 329 public: 330 // T is normalized by calling RSExportType::NormalizeType() before 331 // calling this 332 static bool IsPrimitiveType(const clang::Type *T); 333 334 // @T may not be normalized 335 static RSExportPrimitiveType *Create(RSContext *Context, 336 const clang::Type *T); 337 338 static DataType GetRSSpecificType(const llvm::StringRef &TypeName); 339 static DataType GetRSSpecificType(const clang::Type *T); 340 341 static bool IsRSMatrixType(DataType DT); 342 static bool IsRSObjectType(DataType DT); 343 static bool IsRSObjectType(const clang::Type *T) { 344 return IsRSObjectType(GetRSSpecificType(T)); 345 } 346 347 // Determines whether T is [an array of] struct that contains at least one 348 // RS object type within it. 349 static bool IsStructureTypeWithRSObject(const clang::Type *T); 350 351 // For a primitive type, this is the size of the type. 352 // For a vector type (RSExportVectorType is derived from RSExportPrimitiveType), 353 // this is the size of a single vector element (component). 354 static size_t GetElementSizeInBits(const RSExportPrimitiveType *EPT); 355 356 inline DataType getType() const { return mType; } 357 inline bool isRSObjectType() const { 358 return IsRSObjectType(mType); 359 } 360 361 virtual bool equals(const RSExportable *E) const; 362 363 static RSReflectionType *getRSReflectionType(DataType DT); 364 static RSReflectionType *getRSReflectionType( 365 const RSExportPrimitiveType *EPT) { 366 return getRSReflectionType(EPT->getType()); 367 } 368 369 // For a vector type, this is the size of a single element. 370 unsigned getElementSizeInBytes() const { return (GetElementSizeInBits(this) >> 3); } 371 372 std::string getElementName() const { 373 return getRSReflectionType(this)->rs_short_type; 374 } 375}; // RSExportPrimitiveType 376 377 378class RSExportPointerType : public RSExportType { 379 friend class RSExportType; 380 friend class RSExportFunc; 381 private: 382 const RSExportType *mPointeeType; 383 384 RSExportPointerType(RSContext *Context, 385 const llvm::StringRef &Name, 386 const RSExportType *PointeeType) 387 : RSExportType(Context, ExportClassPointer, Name), 388 mPointeeType(PointeeType) { 389 } 390 391 // @PT was normalized by calling RSExportType::NormalizeType() before calling 392 // this. 393 static RSExportPointerType *Create(RSContext *Context, 394 const clang::PointerType *PT, 395 const llvm::StringRef &TypeName); 396 397 virtual llvm::Type *convertToLLVMType() const; 398 399 public: 400 virtual bool keep(); 401 402 inline const RSExportType *getPointeeType() const { return mPointeeType; } 403 404 virtual bool equals(const RSExportable *E) const; 405}; // RSExportPointerType 406 407 408class RSExportVectorType : public RSExportPrimitiveType { 409 friend class RSExportType; 410 friend class RSExportElement; 411 private: 412 unsigned mNumElement; // number of elements (components) 413 414 RSExportVectorType(RSContext *Context, 415 const llvm::StringRef &Name, 416 DataType DT, 417 bool Normalized, 418 unsigned NumElement) 419 : RSExportPrimitiveType(Context, ExportClassVector, Name, 420 DT, Normalized), 421 mNumElement(NumElement) { 422 } 423 424 // @EVT was normalized by calling RSExportType::NormalizeType() before 425 // calling this. 426 static RSExportVectorType *Create(RSContext *Context, 427 const clang::ExtVectorType *EVT, 428 const llvm::StringRef &TypeName, 429 bool Normalized = false); 430 431 virtual llvm::Type *convertToLLVMType() const; 432 433 public: 434 static llvm::StringRef GetTypeName(const clang::ExtVectorType *EVT); 435 436 inline unsigned getNumElement() const { return mNumElement; } 437 438 std::string getElementName() const { 439 std::stringstream Name; 440 Name << RSExportPrimitiveType::getRSReflectionType(this)->rs_short_type 441 << "_" << getNumElement(); 442 return Name.str(); 443 } 444 445 virtual bool equals(const RSExportable *E) const; 446}; 447 448// Only *square* *float* matrix is supported by now. 449// 450// struct rs_matrix{2x2,3x3,4x4, ..., NxN} should be defined as the following 451// form *exactly*: 452// typedef struct { 453// float m[{NxN}]; 454// } rs_matrixNxN; 455// 456// where mDim will be N. 457class RSExportMatrixType : public RSExportType { 458 friend class RSExportType; 459 private: 460 unsigned mDim; // dimension 461 462 RSExportMatrixType(RSContext *Context, 463 const llvm::StringRef &Name, 464 unsigned Dim) 465 : RSExportType(Context, ExportClassMatrix, Name), 466 mDim(Dim) { 467 } 468 469 virtual llvm::Type *convertToLLVMType() const; 470 471 public: 472 // @RT was normalized by calling RSExportType::NormalizeType() before 473 // calling this. 474 static RSExportMatrixType *Create(RSContext *Context, 475 const clang::RecordType *RT, 476 const llvm::StringRef &TypeName, 477 unsigned Dim); 478 479 inline unsigned getDim() const { return mDim; } 480 481 virtual bool equals(const RSExportable *E) const; 482}; 483 484class RSExportConstantArrayType : public RSExportType { 485 friend class RSExportType; 486 private: 487 const RSExportType *mElementType; // Array element type 488 unsigned mNumElement; // Array element count 489 490 RSExportConstantArrayType(RSContext *Context, 491 const RSExportType *ElementType, 492 unsigned NumElement) 493 : RSExportType(Context, ExportClassConstantArray, "<ConstantArray>"), 494 mElementType(ElementType), 495 mNumElement(NumElement) { 496 } 497 498 // @CAT was normalized by calling RSExportType::NormalizeType() before 499 // calling this. 500 static RSExportConstantArrayType *Create(RSContext *Context, 501 const clang::ConstantArrayType *CAT); 502 503 virtual llvm::Type *convertToLLVMType() const; 504 505 public: 506 unsigned getNumElement() const { return mNumElement; } 507 const RSExportType *getElementType() const { return mElementType; } 508 509 std::string getElementName() const { 510 return mElementType->getElementName(); 511 } 512 513 virtual bool keep(); 514 virtual bool equals(const RSExportable *E) const; 515}; 516 517class RSExportRecordType : public RSExportType { 518 friend class RSExportType; 519 public: 520 class Field { 521 private: 522 const RSExportType *mType; 523 // Field name 524 std::string mName; 525 // Link to the struct that contain this field 526 const RSExportRecordType *mParent; 527 // Offset in the container 528 size_t mOffset; 529 530 public: 531 Field(const RSExportType *T, 532 const llvm::StringRef &Name, 533 const RSExportRecordType *Parent, 534 size_t Offset) 535 : mType(T), 536 mName(Name.data(), Name.size()), 537 mParent(Parent), 538 mOffset(Offset) { 539 } 540 541 inline const RSExportRecordType *getParent() const { return mParent; } 542 inline const RSExportType *getType() const { return mType; } 543 inline const std::string &getName() const { return mName; } 544 inline size_t getOffsetInParent() const { return mOffset; } 545 }; 546 547 typedef std::list<const Field*>::const_iterator const_field_iterator; 548 549 inline const_field_iterator fields_begin() const { 550 return this->mFields.begin(); 551 } 552 inline const_field_iterator fields_end() const { 553 return this->mFields.end(); 554 } 555 556 private: 557 std::list<const Field*> mFields; 558 bool mIsPacked; 559 // Artificial export struct type is not exported by user (and thus it won't 560 // get reflected) 561 bool mIsArtificial; 562 size_t mStoreSize; 563 size_t mAllocSize; 564 565 RSExportRecordType(RSContext *Context, 566 const llvm::StringRef &Name, 567 bool IsPacked, 568 bool IsArtificial, 569 size_t StoreSize, 570 size_t AllocSize) 571 : RSExportType(Context, ExportClassRecord, Name), 572 mIsPacked(IsPacked), 573 mIsArtificial(IsArtificial), 574 mStoreSize(StoreSize), 575 mAllocSize(AllocSize) { 576 } 577 578 // @RT was normalized by calling RSExportType::NormalizeType() before calling 579 // this. 580 // @TypeName was retrieved from RSExportType::GetTypeName() before calling 581 // this. 582 static RSExportRecordType *Create(RSContext *Context, 583 const clang::RecordType *RT, 584 const llvm::StringRef &TypeName, 585 bool mIsArtificial = false); 586 587 virtual llvm::Type *convertToLLVMType() const; 588 589 public: 590 inline const std::list<const Field*>& getFields() const { return mFields; } 591 inline bool isPacked() const { return mIsPacked; } 592 inline bool isArtificial() const { return mIsArtificial; } 593 virtual size_t getStoreSize() const { return mStoreSize; } 594 virtual size_t getAllocSize() const { return mAllocSize; } 595 596 virtual std::string getElementName() const { 597 return "ScriptField_" + getName(); 598 } 599 600 virtual bool keep(); 601 virtual bool equals(const RSExportable *E) const; 602 603 ~RSExportRecordType() { 604 for (std::list<const Field*>::iterator I = mFields.begin(), 605 E = mFields.end(); 606 I != E; 607 I++) 608 if (*I != nullptr) 609 delete *I; 610 } 611}; // RSExportRecordType 612 613} // namespace slang 614 615#endif // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_TYPE_H_ NOLINT 616