Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- RecordLayout.h - Layout information for a struct/union ---*- C++ -*-===// |
2 | // |
||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
4 | // See https://llvm.org/LICENSE.txt for license information. |
||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | // |
||
9 | // This file defines the RecordLayout interface. |
||
10 | // |
||
11 | //===----------------------------------------------------------------------===// |
||
12 | |||
13 | #ifndef LLVM_CLANG_AST_RECORDLAYOUT_H |
||
14 | #define LLVM_CLANG_AST_RECORDLAYOUT_H |
||
15 | |||
16 | #include "clang/AST/ASTVector.h" |
||
17 | #include "clang/AST/CharUnits.h" |
||
18 | #include "clang/AST/DeclCXX.h" |
||
19 | #include "clang/Basic/LLVM.h" |
||
20 | #include "llvm/ADT/ArrayRef.h" |
||
21 | #include "llvm/ADT/DenseMap.h" |
||
22 | #include "llvm/ADT/PointerIntPair.h" |
||
23 | #include <cassert> |
||
24 | #include <cstdint> |
||
25 | |||
26 | namespace clang { |
||
27 | |||
28 | class ASTContext; |
||
29 | class CXXRecordDecl; |
||
30 | |||
31 | /// ASTRecordLayout - |
||
32 | /// This class contains layout information for one RecordDecl, |
||
33 | /// which is a struct/union/class. The decl represented must be a definition, |
||
34 | /// not a forward declaration. |
||
35 | /// This class is also used to contain layout information for one |
||
36 | /// ObjCInterfaceDecl. FIXME - Find appropriate name. |
||
37 | /// These objects are managed by ASTContext. |
||
38 | class ASTRecordLayout { |
||
39 | public: |
||
40 | struct VBaseInfo { |
||
41 | /// The offset to this virtual base in the complete-object layout |
||
42 | /// of this class. |
||
43 | CharUnits VBaseOffset; |
||
44 | |||
45 | private: |
||
46 | /// Whether this virtual base requires a vtordisp field in the |
||
47 | /// Microsoft ABI. These fields are required for certain operations |
||
48 | /// in constructors and destructors. |
||
49 | bool HasVtorDisp = false; |
||
50 | |||
51 | public: |
||
52 | VBaseInfo() = default; |
||
53 | VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) |
||
54 | : VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {} |
||
55 | |||
56 | bool hasVtorDisp() const { return HasVtorDisp; } |
||
57 | }; |
||
58 | |||
59 | using VBaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>; |
||
60 | |||
61 | private: |
||
62 | friend class ASTContext; |
||
63 | |||
64 | /// Size - Size of record in characters. |
||
65 | CharUnits Size; |
||
66 | |||
67 | /// DataSize - Size of record in characters without tail padding. |
||
68 | CharUnits DataSize; |
||
69 | |||
70 | // Alignment - Alignment of record in characters. |
||
71 | CharUnits Alignment; |
||
72 | |||
73 | // PreferredAlignment - Preferred alignment of record in characters. This |
||
74 | // can be different than Alignment in cases where it is beneficial for |
||
75 | // performance or backwards compatibility preserving (e.g. AIX-ABI). |
||
76 | CharUnits PreferredAlignment; |
||
77 | |||
78 | // UnadjustedAlignment - Maximum of the alignments of the record members in |
||
79 | // characters. |
||
80 | CharUnits UnadjustedAlignment; |
||
81 | |||
82 | /// RequiredAlignment - The required alignment of the object. In the MS-ABI |
||
83 | /// the __declspec(align()) trumps #pramga pack and must always be obeyed. |
||
84 | CharUnits RequiredAlignment; |
||
85 | |||
86 | /// FieldOffsets - Array of field offsets in bits. |
||
87 | ASTVector<uint64_t> FieldOffsets; |
||
88 | |||
89 | /// CXXRecordLayoutInfo - Contains C++ specific layout information. |
||
90 | struct CXXRecordLayoutInfo { |
||
91 | /// NonVirtualSize - The non-virtual size (in chars) of an object, which is |
||
92 | /// the size of the object without virtual bases. |
||
93 | CharUnits NonVirtualSize; |
||
94 | |||
95 | /// NonVirtualAlignment - The non-virtual alignment (in chars) of an object, |
||
96 | /// which is the alignment of the object without virtual bases. |
||
97 | CharUnits NonVirtualAlignment; |
||
98 | |||
99 | /// PreferredNVAlignment - The preferred non-virtual alignment (in chars) of |
||
100 | /// an object, which is the preferred alignment of the object without |
||
101 | /// virtual bases. |
||
102 | CharUnits PreferredNVAlignment; |
||
103 | |||
104 | /// SizeOfLargestEmptySubobject - The size of the largest empty subobject |
||
105 | /// (either a base or a member). Will be zero if the class doesn't contain |
||
106 | /// any empty subobjects. |
||
107 | CharUnits SizeOfLargestEmptySubobject; |
||
108 | |||
109 | /// VBPtrOffset - Virtual base table offset (Microsoft-only). |
||
110 | CharUnits VBPtrOffset; |
||
111 | |||
112 | /// HasOwnVFPtr - Does this class provide a virtual function table |
||
113 | /// (vtable in Itanium, vftbl in Microsoft) that is independent from |
||
114 | /// its base classes? |
||
115 | bool HasOwnVFPtr : 1; |
||
116 | |||
117 | /// HasVFPtr - Does this class have a vftable that could be extended by |
||
118 | /// a derived class. The class may have inherited this pointer from |
||
119 | /// a primary base class. |
||
120 | bool HasExtendableVFPtr : 1; |
||
121 | |||
122 | /// EndsWithZeroSizedObject - True if this class contains a zero sized |
||
123 | /// member or base or a base with a zero sized member or base. |
||
124 | /// Only used for MS-ABI. |
||
125 | bool EndsWithZeroSizedObject : 1; |
||
126 | |||
127 | /// True if this class is zero sized or first base is zero sized or |
||
128 | /// has this property. Only used for MS-ABI. |
||
129 | bool LeadsWithZeroSizedBase : 1; |
||
130 | |||
131 | /// PrimaryBase - The primary base info for this record. |
||
132 | llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; |
||
133 | |||
134 | /// BaseSharingVBPtr - The base we share vbptr with. |
||
135 | const CXXRecordDecl *BaseSharingVBPtr; |
||
136 | |||
137 | /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) |
||
138 | using BaseOffsetsMapTy = llvm::DenseMap<const CXXRecordDecl *, CharUnits>; |
||
139 | |||
140 | /// BaseOffsets - Contains a map from base classes to their offset. |
||
141 | BaseOffsetsMapTy BaseOffsets; |
||
142 | |||
143 | /// VBaseOffsets - Contains a map from vbase classes to their offset. |
||
144 | VBaseOffsetsMapTy VBaseOffsets; |
||
145 | }; |
||
146 | |||
147 | /// CXXInfo - If the record layout is for a C++ record, this will have |
||
148 | /// C++ specific information about the record. |
||
149 | CXXRecordLayoutInfo *CXXInfo = nullptr; |
||
150 | |||
151 | ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, |
||
152 | CharUnits preferredAlignment, CharUnits unadjustedAlignment, |
||
153 | CharUnits requiredAlignment, CharUnits datasize, |
||
154 | ArrayRef<uint64_t> fieldoffsets); |
||
155 | |||
156 | using BaseOffsetsMapTy = CXXRecordLayoutInfo::BaseOffsetsMapTy; |
||
157 | |||
158 | // Constructor for C++ records. |
||
159 | ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, |
||
160 | CharUnits preferredAlignment, CharUnits unadjustedAlignment, |
||
161 | CharUnits requiredAlignment, bool hasOwnVFPtr, |
||
162 | bool hasExtendableVFPtr, CharUnits vbptroffset, |
||
163 | CharUnits datasize, ArrayRef<uint64_t> fieldoffsets, |
||
164 | CharUnits nonvirtualsize, CharUnits nonvirtualalignment, |
||
165 | CharUnits preferrednvalignment, |
||
166 | CharUnits SizeOfLargestEmptySubobject, |
||
167 | const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual, |
||
168 | const CXXRecordDecl *BaseSharingVBPtr, |
||
169 | bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase, |
||
170 | const BaseOffsetsMapTy &BaseOffsets, |
||
171 | const VBaseOffsetsMapTy &VBaseOffsets); |
||
172 | |||
173 | ~ASTRecordLayout() = default; |
||
174 | |||
175 | void Destroy(ASTContext &Ctx); |
||
176 | |||
177 | public: |
||
178 | ASTRecordLayout(const ASTRecordLayout &) = delete; |
||
179 | ASTRecordLayout &operator=(const ASTRecordLayout &) = delete; |
||
180 | |||
181 | /// getAlignment - Get the record alignment in characters. |
||
182 | CharUnits getAlignment() const { return Alignment; } |
||
183 | |||
184 | /// getPreferredFieldAlignment - Get the record preferred alignment in |
||
185 | /// characters. |
||
186 | CharUnits getPreferredAlignment() const { return PreferredAlignment; } |
||
187 | |||
188 | /// getUnadjustedAlignment - Get the record alignment in characters, before |
||
189 | /// alignment adjustement. |
||
190 | CharUnits getUnadjustedAlignment() const { return UnadjustedAlignment; } |
||
191 | |||
192 | /// getSize - Get the record size in characters. |
||
193 | CharUnits getSize() const { return Size; } |
||
194 | |||
195 | /// getFieldCount - Get the number of fields in the layout. |
||
196 | unsigned getFieldCount() const { return FieldOffsets.size(); } |
||
197 | |||
198 | /// getFieldOffset - Get the offset of the given field index, in |
||
199 | /// bits. |
||
200 | uint64_t getFieldOffset(unsigned FieldNo) const { |
||
201 | return FieldOffsets[FieldNo]; |
||
202 | } |
||
203 | |||
204 | /// getDataSize() - Get the record data size, which is the record size |
||
205 | /// without tail padding, in characters. |
||
206 | CharUnits getDataSize() const { return DataSize; } |
||
207 | |||
208 | /// getNonVirtualSize - Get the non-virtual size (in chars) of an object, |
||
209 | /// which is the size of the object without virtual bases. |
||
210 | CharUnits getNonVirtualSize() const { |
||
211 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
212 | |||
213 | return CXXInfo->NonVirtualSize; |
||
214 | } |
||
215 | |||
216 | /// getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an |
||
217 | /// object, which is the alignment of the object without virtual bases. |
||
218 | CharUnits getNonVirtualAlignment() const { |
||
219 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
220 | |||
221 | return CXXInfo->NonVirtualAlignment; |
||
222 | } |
||
223 | |||
224 | /// getPreferredNVAlignment - Get the preferred non-virtual alignment (in |
||
225 | /// chars) of an object, which is the preferred alignment of the object |
||
226 | /// without virtual bases. |
||
227 | CharUnits getPreferredNVAlignment() const { |
||
228 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
229 | |||
230 | return CXXInfo->PreferredNVAlignment; |
||
231 | } |
||
232 | |||
233 | /// getPrimaryBase - Get the primary base for this record. |
||
234 | const CXXRecordDecl *getPrimaryBase() const { |
||
235 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
236 | |||
237 | return CXXInfo->PrimaryBase.getPointer(); |
||
238 | } |
||
239 | |||
240 | /// isPrimaryBaseVirtual - Get whether the primary base for this record |
||
241 | /// is virtual or not. |
||
242 | bool isPrimaryBaseVirtual() const { |
||
243 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
244 | |||
245 | return CXXInfo->PrimaryBase.getInt(); |
||
246 | } |
||
247 | |||
248 | /// getBaseClassOffset - Get the offset, in chars, for the given base class. |
||
249 | CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const { |
||
250 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
251 | |||
252 | Base = Base->getDefinition(); |
||
253 | assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); |
||
254 | |||
255 | return CXXInfo->BaseOffsets[Base]; |
||
256 | } |
||
257 | |||
258 | /// getVBaseClassOffset - Get the offset, in chars, for the given base class. |
||
259 | CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const { |
||
260 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
261 | |||
262 | VBase = VBase->getDefinition(); |
||
263 | assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); |
||
264 | |||
265 | return CXXInfo->VBaseOffsets[VBase].VBaseOffset; |
||
266 | } |
||
267 | |||
268 | CharUnits getSizeOfLargestEmptySubobject() const { |
||
269 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
270 | return CXXInfo->SizeOfLargestEmptySubobject; |
||
271 | } |
||
272 | |||
273 | /// hasOwnVFPtr - Does this class provide its own virtual-function |
||
274 | /// table pointer, rather than inheriting one from a primary base |
||
275 | /// class? If so, it is at offset zero. |
||
276 | /// |
||
277 | /// This implies that the ABI has no primary base class, meaning |
||
278 | /// that it has no base classes that are suitable under the conditions |
||
279 | /// of the ABI. |
||
280 | bool hasOwnVFPtr() const { |
||
281 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
282 | return CXXInfo->HasOwnVFPtr; |
||
283 | } |
||
284 | |||
285 | /// hasVFPtr - Does this class have a virtual function table pointer |
||
286 | /// that can be extended by a derived class? This is synonymous with |
||
287 | /// this class having a VFPtr at offset zero. |
||
288 | bool hasExtendableVFPtr() const { |
||
289 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
290 | return CXXInfo->HasExtendableVFPtr; |
||
291 | } |
||
292 | |||
293 | /// hasOwnVBPtr - Does this class provide its own virtual-base |
||
294 | /// table pointer, rather than inheriting one from a primary base |
||
295 | /// class? |
||
296 | /// |
||
297 | /// This implies that the ABI has no primary base class, meaning |
||
298 | /// that it has no base classes that are suitable under the conditions |
||
299 | /// of the ABI. |
||
300 | bool hasOwnVBPtr() const { |
||
301 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
302 | return hasVBPtr() && !CXXInfo->BaseSharingVBPtr; |
||
303 | } |
||
304 | |||
305 | /// hasVBPtr - Does this class have a virtual function table pointer. |
||
306 | bool hasVBPtr() const { |
||
307 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
308 | return !CXXInfo->VBPtrOffset.isNegative(); |
||
309 | } |
||
310 | |||
311 | CharUnits getRequiredAlignment() const { return RequiredAlignment; } |
||
312 | |||
313 | bool endsWithZeroSizedObject() const { |
||
314 | return CXXInfo && CXXInfo->EndsWithZeroSizedObject; |
||
315 | } |
||
316 | |||
317 | bool leadsWithZeroSizedBase() const { |
||
318 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
319 | return CXXInfo->LeadsWithZeroSizedBase; |
||
320 | } |
||
321 | |||
322 | /// getVBPtrOffset - Get the offset for virtual base table pointer. |
||
323 | /// This is only meaningful with the Microsoft ABI. |
||
324 | CharUnits getVBPtrOffset() const { |
||
325 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
326 | return CXXInfo->VBPtrOffset; |
||
327 | } |
||
328 | |||
329 | const CXXRecordDecl *getBaseSharingVBPtr() const { |
||
330 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
331 | return CXXInfo->BaseSharingVBPtr; |
||
332 | } |
||
333 | |||
334 | const VBaseOffsetsMapTy &getVBaseOffsetsMap() const { |
||
335 | assert(CXXInfo && "Record layout does not have C++ specific info!"); |
||
336 | return CXXInfo->VBaseOffsets; |
||
337 | } |
||
338 | }; |
||
339 | |||
340 | } // namespace clang |
||
341 | |||
342 | #endif // LLVM_CLANG_AST_RECORDLAYOUT_H |