RecordLayout.h revision 478851c3ed6bd784e7377dffd8e57b200c1b9ba9
1//===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines the RecordLayout interface.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
15#define LLVM_CLANG_AST_LAYOUTINFO_H
16
17#include "clang/AST/ASTContext.h"
18#include "clang/AST/CharUnits.h"
19#include "clang/AST/DeclCXX.h"
20#include "llvm/ADT/DenseMap.h"
21
22namespace clang {
23  class ASTContext;
24  class FieldDecl;
25  class RecordDecl;
26  class CXXRecordDecl;
27
28/// ASTRecordLayout -
29/// This class contains layout information for one RecordDecl,
30/// which is a struct/union/class.  The decl represented must be a definition,
31/// not a forward declaration.
32/// This class is also used to contain layout information for one
33/// ObjCInterfaceDecl. FIXME - Find appropriate name.
34/// These objects are managed by ASTContext.
35class ASTRecordLayout {
36public:
37  struct VBaseInfo {
38    /// The offset to this virtual base in the complete-object layout
39    /// of this class.
40    CharUnits VBaseOffset;
41
42  private:
43    /// Whether this virtual base requires a vtordisp field in the
44    /// Microsoft ABI.  These fields are required for certain operations
45    /// in constructors and destructors.
46    bool HasVtorDisp;
47
48  public:
49    bool hasVtorDisp() const { return HasVtorDisp; }
50
51    VBaseInfo() : HasVtorDisp(false) {}
52
53    VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) :
54     VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {}
55  };
56
57  typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>
58    VBaseOffsetsMapTy;
59
60private:
61  /// Size - Size of record in characters.
62  CharUnits Size;
63
64  /// DataSize - Size of record in characters without tail padding.
65  CharUnits DataSize;
66
67  // Alignment - Alignment of record in characters.
68  CharUnits Alignment;
69
70  /// FieldOffsets - Array of field offsets in bits.
71  uint64_t *FieldOffsets;
72
73  // FieldCount - Number of fields.
74  unsigned FieldCount;
75
76  /// CXXRecordLayoutInfo - Contains C++ specific layout information.
77  struct CXXRecordLayoutInfo {
78    /// NonVirtualSize - The non-virtual size (in chars) of an object, which is
79    /// the size of the object without virtual bases.
80    CharUnits NonVirtualSize;
81
82    /// NonVirtualAlign - The non-virtual alignment (in chars) of an object,
83    /// which is the alignment of the object without virtual bases.
84    CharUnits NonVirtualAlign;
85
86    /// SizeOfLargestEmptySubobject - The size of the largest empty subobject
87    /// (either a base or a member). Will be zero if the class doesn't contain
88    /// any empty subobjects.
89    CharUnits SizeOfLargestEmptySubobject;
90
91    /// VBPtrOffset - Virtual base table offset (Microsoft-only).
92    CharUnits VBPtrOffset;
93
94    /// HasOwnVFPtr - Does this class provide a virtual function table
95    /// (vtable in Itanium, vftbl in Microsoft) that is independent from
96    /// its base classes?
97    bool HasOwnVFPtr; // TODO: stash this somewhere more efficient
98
99    /// PrimaryBase - The primary base info for this record.
100    llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
101
102    /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
103    typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
104
105    /// BaseOffsets - Contains a map from base classes to their offset.
106    BaseOffsetsMapTy BaseOffsets;
107
108    /// VBaseOffsets - Contains a map from vbase classes to their offset.
109    VBaseOffsetsMapTy VBaseOffsets;
110  };
111
112  /// CXXInfo - If the record layout is for a C++ record, this will have
113  /// C++ specific information about the record.
114  CXXRecordLayoutInfo *CXXInfo;
115
116  friend class ASTContext;
117
118  ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
119                  CharUnits datasize, const uint64_t *fieldoffsets,
120                  unsigned fieldcount);
121
122  // Constructor for C++ records.
123  typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
124  ASTRecordLayout(const ASTContext &Ctx,
125                  CharUnits size, CharUnits alignment,
126                  bool hasOwnVFPtr, CharUnits vbptroffset,
127                  CharUnits datasize,
128                  const uint64_t *fieldoffsets, unsigned fieldcount,
129                  CharUnits nonvirtualsize, CharUnits nonvirtualalign,
130                  CharUnits SizeOfLargestEmptySubobject,
131                  const CXXRecordDecl *PrimaryBase,
132                  bool IsPrimaryBaseVirtual,
133                  const BaseOffsetsMapTy& BaseOffsets,
134                  const VBaseOffsetsMapTy& VBaseOffsets);
135
136  ~ASTRecordLayout() {}
137
138  void Destroy(ASTContext &Ctx);
139
140  ASTRecordLayout(const ASTRecordLayout&);   // DO NOT IMPLEMENT
141  void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT
142public:
143
144  /// getAlignment - Get the record alignment in characters.
145  CharUnits getAlignment() const { return Alignment; }
146
147  /// getSize - Get the record size in characters.
148  CharUnits getSize() const { return Size; }
149
150  /// getFieldCount - Get the number of fields in the layout.
151  unsigned getFieldCount() const { return FieldCount; }
152
153  /// getFieldOffset - Get the offset of the given field index, in
154  /// bits.
155  uint64_t getFieldOffset(unsigned FieldNo) const {
156    assert (FieldNo < FieldCount && "Invalid Field No");
157    return FieldOffsets[FieldNo];
158  }
159
160  /// getDataSize() - Get the record data size, which is the record size
161  /// without tail padding, in characters.
162  CharUnits getDataSize() const {
163    return DataSize;
164  }
165
166  /// getNonVirtualSize - Get the non-virtual size (in chars) of an object,
167  /// which is the size of the object without virtual bases.
168  CharUnits getNonVirtualSize() const {
169    assert(CXXInfo && "Record layout does not have C++ specific info!");
170
171    return CXXInfo->NonVirtualSize;
172  }
173
174  /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object,
175  /// which is the alignment of the object without virtual bases.
176  CharUnits getNonVirtualAlign() const {
177    assert(CXXInfo && "Record layout does not have C++ specific info!");
178
179    return CXXInfo->NonVirtualAlign;
180  }
181
182  /// getPrimaryBase - Get the primary base for this record.
183  const CXXRecordDecl *getPrimaryBase() const {
184    assert(CXXInfo && "Record layout does not have C++ specific info!");
185
186    return CXXInfo->PrimaryBase.getPointer();
187  }
188
189  /// isPrimaryBaseVirtual - Get whether the primary base for this record
190  /// is virtual or not.
191  bool isPrimaryBaseVirtual() const {
192    assert(CXXInfo && "Record layout does not have C++ specific info!");
193
194    return CXXInfo->PrimaryBase.getInt();
195  }
196
197  /// getBaseClassOffset - Get the offset, in chars, for the given base class.
198  CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const {
199    assert(CXXInfo && "Record layout does not have C++ specific info!");
200    assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
201
202    return CXXInfo->BaseOffsets[Base];
203  }
204
205  /// getVBaseClassOffset - Get the offset, in chars, for the given base class.
206  CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const {
207    assert(CXXInfo && "Record layout does not have C++ specific info!");
208    assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
209
210    return CXXInfo->VBaseOffsets[VBase].VBaseOffset;
211  }
212
213  /// getBaseClassOffsetInBits - Get the offset, in bits, for the given
214  /// base class.
215  uint64_t getBaseClassOffsetInBits(const CXXRecordDecl *Base) const {
216    assert(CXXInfo && "Record layout does not have C++ specific info!");
217    assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
218
219    return getBaseClassOffset(Base).getQuantity() *
220      Base->getASTContext().getCharWidth();
221  }
222
223  /// getVBaseClassOffsetInBits - Get the offset, in bits, for the given
224  /// base class.
225  uint64_t getVBaseClassOffsetInBits(const CXXRecordDecl *VBase) const {
226    assert(CXXInfo && "Record layout does not have C++ specific info!");
227    assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
228
229    return getVBaseClassOffset(VBase).getQuantity() *
230      VBase->getASTContext().getCharWidth();
231  }
232
233  CharUnits getSizeOfLargestEmptySubobject() const {
234    assert(CXXInfo && "Record layout does not have C++ specific info!");
235    return CXXInfo->SizeOfLargestEmptySubobject;
236  }
237
238  /// hasOwnVFPtr - Does this class provide its own virtual-function
239  /// table pointer, rather than inheriting one from a primary base
240  /// class?  If so, it is at offset zero.
241  ///
242  /// This implies that the ABI has no primary base class, meaning
243  /// that it has no base classes that are suitable under the conditions
244  /// of the ABI.
245  bool hasOwnVFPtr() const {
246    assert(CXXInfo && "Record layout does not have C++ specific info!");
247    return CXXInfo->HasOwnVFPtr;
248  }
249
250  /// getVBPtrOffset - Get the offset for virtual base table pointer.
251  /// This is only meaningful with the Microsoft ABI.
252  CharUnits getVBPtrOffset() const {
253    assert(CXXInfo && "Record layout does not have C++ specific info!");
254    return CXXInfo->VBPtrOffset;
255  }
256
257  const VBaseOffsetsMapTy &getVBaseOffsetsMap() const {
258    assert(CXXInfo && "Record layout does not have C++ specific info!");
259    return CXXInfo->VBaseOffsets;
260  }
261};
262
263}  // end namespace clang
264
265#endif
266