1193326Sed//===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file defines the RecordLayout interface.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
15193326Sed#define LLVM_CLANG_AST_LAYOUTINFO_H
16193326Sed
17218893Sdim#include "clang/AST/CharUnits.h"
18199482Srdivacky#include "clang/AST/DeclCXX.h"
19239462Sdim#include "llvm/ADT/DenseMap.h"
20193326Sed
21193326Sednamespace clang {
22193326Sed  class ASTContext;
23198092Srdivacky  class FieldDecl;
24193326Sed  class RecordDecl;
25198092Srdivacky  class CXXRecordDecl;
26193326Sed
27198092Srdivacky/// ASTRecordLayout -
28193326Sed/// This class contains layout information for one RecordDecl,
29193326Sed/// which is a struct/union/class.  The decl represented must be a definition,
30198092Srdivacky/// not a forward declaration.
31198092Srdivacky/// This class is also used to contain layout information for one
32193326Sed/// ObjCInterfaceDecl. FIXME - Find appropriate name.
33193326Sed/// These objects are managed by ASTContext.
34193326Sedclass ASTRecordLayout {
35239462Sdimpublic:
36239462Sdim  struct VBaseInfo {
37239462Sdim    /// The offset to this virtual base in the complete-object layout
38239462Sdim    /// of this class.
39239462Sdim    CharUnits VBaseOffset;
40239462Sdim
41239462Sdim  private:
42239462Sdim    /// Whether this virtual base requires a vtordisp field in the
43239462Sdim    /// Microsoft ABI.  These fields are required for certain operations
44239462Sdim    /// in constructors and destructors.
45239462Sdim    bool HasVtorDisp;
46239462Sdim
47239462Sdim  public:
48239462Sdim    bool hasVtorDisp() const { return HasVtorDisp; }
49239462Sdim
50239462Sdim    VBaseInfo() : HasVtorDisp(false) {}
51239462Sdim
52239462Sdim    VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) :
53239462Sdim     VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {}
54239462Sdim  };
55239462Sdim
56239462Sdim  typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>
57239462Sdim    VBaseOffsetsMapTy;
58239462Sdim
59239462Sdimprivate:
60218893Sdim  /// Size - Size of record in characters.
61218893Sdim  CharUnits Size;
62198092Srdivacky
63218893Sdim  /// DataSize - Size of record in characters without tail padding.
64218893Sdim  CharUnits DataSize;
65198092Srdivacky
66239462Sdim  // Alignment - Alignment of record in characters.
67239462Sdim  CharUnits Alignment;
68239462Sdim
69198092Srdivacky  /// FieldOffsets - Array of field offsets in bits.
70193326Sed  uint64_t *FieldOffsets;
71198092Srdivacky
72198092Srdivacky  // FieldCount - Number of fields.
73198092Srdivacky  unsigned FieldCount;
74198092Srdivacky
75199990Srdivacky  /// CXXRecordLayoutInfo - Contains C++ specific layout information.
76198092Srdivacky  struct CXXRecordLayoutInfo {
77218893Sdim    /// NonVirtualSize - The non-virtual size (in chars) of an object, which is
78198092Srdivacky    /// the size of the object without virtual bases.
79218893Sdim    CharUnits NonVirtualSize;
80198092Srdivacky
81218893Sdim    /// NonVirtualAlign - The non-virtual alignment (in chars) of an object,
82198092Srdivacky    /// which is the alignment of the object without virtual bases.
83218893Sdim    CharUnits NonVirtualAlign;
84198092Srdivacky
85208600Srdivacky    /// SizeOfLargestEmptySubobject - The size of the largest empty subobject
86208600Srdivacky    /// (either a base or a member). Will be zero if the class doesn't contain
87208600Srdivacky    /// any empty subobjects.
88218893Sdim    CharUnits SizeOfLargestEmptySubobject;
89234353Sdim
90234353Sdim    /// VBPtrOffset - Virtual base table offset (Microsoft-only).
91226633Sdim    CharUnits VBPtrOffset;
92239462Sdim
93239462Sdim    /// HasOwnVFPtr - Does this class provide a virtual function table
94239462Sdim    /// (vtable in Itanium, vftbl in Microsoft) that is independent from
95239462Sdim    /// its base classes?
96263508Sdim    bool HasOwnVFPtr : 1;
97263508Sdim
98263508Sdim    /// HasVFPtr - Does this class have a vftable that could be extended by
99263508Sdim    /// a derived class.  The class may have inherited this pointer from
100263508Sdim    /// a primary base class.
101263508Sdim    bool HasExtendableVFPtr : 1;
102263508Sdim
103263508Sdim    /// AlignAfterVBases - Force appropriate alignment after virtual bases are
104263508Sdim    /// laid out in MS-C++-ABI.
105263508Sdim    bool AlignAfterVBases : 1;
106226633Sdim
107199990Srdivacky    /// PrimaryBase - The primary base info for this record.
108218893Sdim    llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
109263508Sdim
110263508Sdim    /// BaseSharingVBPtr - The base we share vbptr with.
111263508Sdim    const CXXRecordDecl *BaseSharingVBPtr;
112199990Srdivacky
113205219Srdivacky    /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
114218893Sdim    typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
115205219Srdivacky
116198092Srdivacky    /// BaseOffsets - Contains a map from base classes to their offset.
117205219Srdivacky    BaseOffsetsMapTy BaseOffsets;
118198092Srdivacky
119198092Srdivacky    /// VBaseOffsets - Contains a map from vbase classes to their offset.
120239462Sdim    VBaseOffsetsMapTy VBaseOffsets;
121198092Srdivacky  };
122198092Srdivacky
123198092Srdivacky  /// CXXInfo - If the record layout is for a C++ record, this will have
124198092Srdivacky  /// C++ specific information about the record.
125198092Srdivacky  CXXRecordLayoutInfo *CXXInfo;
126198092Srdivacky
127193326Sed  friend class ASTContext;
128193326Sed
129218893Sdim  ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
130218893Sdim                  CharUnits datasize, const uint64_t *fieldoffsets,
131204962Srdivacky                  unsigned fieldcount);
132193326Sed
133198092Srdivacky  // Constructor for C++ records.
134205219Srdivacky  typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
135218893Sdim  ASTRecordLayout(const ASTContext &Ctx,
136234353Sdim                  CharUnits size, CharUnits alignment,
137263508Sdim                  bool hasOwnVFPtr, bool hasExtendableVFPtr,
138263508Sdim                  CharUnits vbptroffset,
139226633Sdim                  CharUnits datasize,
140198092Srdivacky                  const uint64_t *fieldoffsets, unsigned fieldcount,
141218893Sdim                  CharUnits nonvirtualsize, CharUnits nonvirtualalign,
142218893Sdim                  CharUnits SizeOfLargestEmptySubobject,
143208600Srdivacky                  const CXXRecordDecl *PrimaryBase,
144218893Sdim                  bool IsPrimaryBaseVirtual,
145263508Sdim                  const CXXRecordDecl *BaseSharingVBPtr,
146263508Sdim                  bool ForceAlign,
147205219Srdivacky                  const BaseOffsetsMapTy& BaseOffsets,
148239462Sdim                  const VBaseOffsetsMapTy& VBaseOffsets);
149193326Sed
150204962Srdivacky  ~ASTRecordLayout() {}
151193326Sed
152204962Srdivacky  void Destroy(ASTContext &Ctx);
153218893Sdim
154243830Sdim  ASTRecordLayout(const ASTRecordLayout &) LLVM_DELETED_FUNCTION;
155243830Sdim  void operator=(const ASTRecordLayout &) LLVM_DELETED_FUNCTION;
156193326Sedpublic:
157198092Srdivacky
158218893Sdim  /// getAlignment - Get the record alignment in characters.
159218893Sdim  CharUnits getAlignment() const { return Alignment; }
160193326Sed
161218893Sdim  /// getSize - Get the record size in characters.
162218893Sdim  CharUnits getSize() const { return Size; }
163198092Srdivacky
164193326Sed  /// getFieldCount - Get the number of fields in the layout.
165193326Sed  unsigned getFieldCount() const { return FieldCount; }
166198092Srdivacky
167193326Sed  /// getFieldOffset - Get the offset of the given field index, in
168193326Sed  /// bits.
169193326Sed  uint64_t getFieldOffset(unsigned FieldNo) const {
170193326Sed    assert (FieldNo < FieldCount && "Invalid Field No");
171193326Sed    return FieldOffsets[FieldNo];
172193326Sed  }
173198092Srdivacky
174198092Srdivacky  /// getDataSize() - Get the record data size, which is the record size
175218893Sdim  /// without tail padding, in characters.
176218893Sdim  CharUnits getDataSize() const {
177198092Srdivacky    return DataSize;
178193326Sed  }
179198092Srdivacky
180218893Sdim  /// getNonVirtualSize - Get the non-virtual size (in chars) of an object,
181198092Srdivacky  /// which is the size of the object without virtual bases.
182218893Sdim  CharUnits getNonVirtualSize() const {
183198092Srdivacky    assert(CXXInfo && "Record layout does not have C++ specific info!");
184198092Srdivacky
185198092Srdivacky    return CXXInfo->NonVirtualSize;
186198092Srdivacky  }
187198092Srdivacky
188218893Sdim  /// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object,
189198092Srdivacky  /// which is the alignment of the object without virtual bases.
190218893Sdim  CharUnits getNonVirtualAlign() const {
191198092Srdivacky    assert(CXXInfo && "Record layout does not have C++ specific info!");
192198092Srdivacky
193198092Srdivacky    return CXXInfo->NonVirtualAlign;
194198092Srdivacky  }
195198092Srdivacky
196218893Sdim  /// getPrimaryBase - Get the primary base for this record.
197218893Sdim  const CXXRecordDecl *getPrimaryBase() const {
198198092Srdivacky    assert(CXXInfo && "Record layout does not have C++ specific info!");
199198092Srdivacky
200218893Sdim    return CXXInfo->PrimaryBase.getPointer();
201198092Srdivacky  }
202198092Srdivacky
203218893Sdim  /// isPrimaryBaseVirtual - Get whether the primary base for this record
204218893Sdim  /// is virtual or not.
205218893Sdim  bool isPrimaryBaseVirtual() const {
206218893Sdim    assert(CXXInfo && "Record layout does not have C++ specific info!");
207198092Srdivacky
208218893Sdim    return CXXInfo->PrimaryBase.getInt();
209199990Srdivacky  }
210199990Srdivacky
211218893Sdim  /// getBaseClassOffset - Get the offset, in chars, for the given base class.
212218893Sdim  CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const {
213198092Srdivacky    assert(CXXInfo && "Record layout does not have C++ specific info!");
214198092Srdivacky    assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
215198092Srdivacky
216198092Srdivacky    return CXXInfo->BaseOffsets[Base];
217198092Srdivacky  }
218198092Srdivacky
219218893Sdim  /// getVBaseClassOffset - Get the offset, in chars, for the given base class.
220218893Sdim  CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const {
221198092Srdivacky    assert(CXXInfo && "Record layout does not have C++ specific info!");
222198092Srdivacky    assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
223198092Srdivacky
224239462Sdim    return CXXInfo->VBaseOffsets[VBase].VBaseOffset;
225198092Srdivacky  }
226218893Sdim
227218893Sdim  CharUnits getSizeOfLargestEmptySubobject() const {
228199990Srdivacky    assert(CXXInfo && "Record layout does not have C++ specific info!");
229218893Sdim    return CXXInfo->SizeOfLargestEmptySubobject;
230199990Srdivacky  }
231226633Sdim
232239462Sdim  /// hasOwnVFPtr - Does this class provide its own virtual-function
233239462Sdim  /// table pointer, rather than inheriting one from a primary base
234239462Sdim  /// class?  If so, it is at offset zero.
235239462Sdim  ///
236239462Sdim  /// This implies that the ABI has no primary base class, meaning
237239462Sdim  /// that it has no base classes that are suitable under the conditions
238239462Sdim  /// of the ABI.
239239462Sdim  bool hasOwnVFPtr() const {
240234353Sdim    assert(CXXInfo && "Record layout does not have C++ specific info!");
241239462Sdim    return CXXInfo->HasOwnVFPtr;
242234353Sdim  }
243234353Sdim
244263508Sdim  /// hasVFPtr - Does this class have a virtual function table pointer
245263508Sdim  /// that can be extended by a derived class?  This is synonymous with
246263508Sdim  /// this class having a VFPtr at offset zero.
247263508Sdim  bool hasExtendableVFPtr() const {
248263508Sdim    assert(CXXInfo && "Record layout does not have C++ specific info!");
249263508Sdim    return CXXInfo->HasExtendableVFPtr;
250263508Sdim  }
251263508Sdim
252263508Sdim  /// hasOwnVBPtr - Does this class provide its own virtual-base
253263508Sdim  /// table pointer, rather than inheriting one from a primary base
254263508Sdim  /// class?
255263508Sdim  ///
256263508Sdim  /// This implies that the ABI has no primary base class, meaning
257263508Sdim  /// that it has no base classes that are suitable under the conditions
258263508Sdim  /// of the ABI.
259263508Sdim  bool hasOwnVBPtr() const {
260263508Sdim    assert(CXXInfo && "Record layout does not have C++ specific info!");
261263508Sdim    return hasVBPtr() && !CXXInfo->BaseSharingVBPtr;
262263508Sdim  }
263263508Sdim
264263508Sdim  /// hasVBPtr - Does this class have a virtual function table pointer.
265263508Sdim  bool hasVBPtr() const {
266263508Sdim    assert(CXXInfo && "Record layout does not have C++ specific info!");
267263508Sdim    return !CXXInfo->VBPtrOffset.isNegative();
268263508Sdim  }
269263508Sdim
270263508Sdim  bool getAlignAfterVBases() const {
271263508Sdim    assert(CXXInfo && "Record layout does not have C++ specific info!");
272263508Sdim    return CXXInfo->AlignAfterVBases;
273263508Sdim  }
274263508Sdim
275234353Sdim  /// getVBPtrOffset - Get the offset for virtual base table pointer.
276234353Sdim  /// This is only meaningful with the Microsoft ABI.
277226633Sdim  CharUnits getVBPtrOffset() const {
278234353Sdim    assert(CXXInfo && "Record layout does not have C++ specific info!");
279226633Sdim    return CXXInfo->VBPtrOffset;
280226633Sdim  }
281239462Sdim
282263508Sdim  const CXXRecordDecl *getBaseSharingVBPtr() const {
283263508Sdim    assert(CXXInfo && "Record layout does not have C++ specific info!");
284263508Sdim    return CXXInfo->BaseSharingVBPtr;
285263508Sdim  }
286263508Sdim
287239462Sdim  const VBaseOffsetsMapTy &getVBaseOffsetsMap() const {
288239462Sdim    assert(CXXInfo && "Record layout does not have C++ specific info!");
289239462Sdim    return CXXInfo->VBaseOffsets;
290239462Sdim  }
291193326Sed};
292193326Sed
293193326Sed}  // end namespace clang
294193326Sed
295193326Sed#endif
296