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