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