1 //===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the RecordLayout interface.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_AST_LAYOUTINFO_H
15 #define LLVM_CLANG_AST_LAYOUTINFO_H
17 #include "llvm/System/DataTypes.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "clang/AST/DeclCXX.h"
28 /// This class contains layout information for one RecordDecl,
29 /// which is a struct/union/class. The decl represented must be a definition,
30 /// not a forward declaration.
31 /// This class is also used to contain layout information for one
32 /// ObjCInterfaceDecl. FIXME - Find appropriate name.
33 /// These objects are managed by ASTContext.
34 class ASTRecordLayout {
35 /// Size - Size of record in bits.
38 /// DataSize - Size of record in bits without tail padding.
41 /// FieldOffsets - Array of field offsets in bits.
42 uint64_t *FieldOffsets;
44 // Alignment - Alignment of record in bits.
47 // FieldCount - Number of fields.
51 /// PrimaryBaseInfo - Contains info about a primary base.
52 struct PrimaryBaseInfo {
55 PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual)
56 : Value(Base, Base && IsVirtual) {}
58 /// Value - Points to the primary base. The single-bit value
59 /// will be non-zero when the primary base is virtual.
60 llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Value;
62 /// getBase - Returns the primary base.
63 const CXXRecordDecl *getBase() const { return Value.getPointer(); }
65 /// isVirtual - Returns whether the primary base is virtual or not.
66 bool isVirtual() const { return Value.getInt(); }
68 friend bool operator==(const PrimaryBaseInfo &X, const PrimaryBaseInfo &Y) {
69 return X.Value == Y.Value;
73 /// primary_base_info_iterator - An iterator for iterating the primary base
75 class primary_base_info_iterator {
76 /// Current - The current base class info.
77 PrimaryBaseInfo Current;
80 primary_base_info_iterator() {}
81 primary_base_info_iterator(PrimaryBaseInfo Info) : Current(Info) {}
83 const PrimaryBaseInfo &operator*() const { return Current; }
85 primary_base_info_iterator& operator++() {
86 const CXXRecordDecl *RD = Current.getBase();
87 Current = RD->getASTContext().getASTRecordLayout(RD).getPrimaryBaseInfo();
91 friend bool operator==(const primary_base_info_iterator &X,
92 const primary_base_info_iterator &Y) {
93 return X.Current == Y.Current;
95 friend bool operator!=(const primary_base_info_iterator &X,
96 const primary_base_info_iterator &Y) {
102 /// CXXRecordLayoutInfo - Contains C++ specific layout information.
103 struct CXXRecordLayoutInfo {
104 /// NonVirtualSize - The non-virtual size (in bits) of an object, which is
105 /// the size of the object without virtual bases.
106 uint64_t NonVirtualSize;
108 /// NonVirtualAlign - The non-virtual alignment (in bits) of an object,
109 /// which is the alignment of the object without virtual bases.
110 uint64_t NonVirtualAlign;
112 /// SizeOfLargestEmptySubobject - The size of the largest empty subobject
113 /// (either a base or a member). Will be zero if the class doesn't contain
114 /// any empty subobjects.
115 uint64_t SizeOfLargestEmptySubobject;
117 /// PrimaryBase - The primary base info for this record.
118 PrimaryBaseInfo PrimaryBase;
120 /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
121 typedef llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsetsMapTy;
123 /// BaseOffsets - Contains a map from base classes to their offset.
124 BaseOffsetsMapTy BaseOffsets;
126 /// VBaseOffsets - Contains a map from vbase classes to their offset.
127 BaseOffsetsMapTy VBaseOffsets;
130 /// CXXInfo - If the record layout is for a C++ record, this will have
131 /// C++ specific information about the record.
132 CXXRecordLayoutInfo *CXXInfo;
134 friend class ASTContext;
136 ASTRecordLayout(ASTContext &Ctx, uint64_t size, unsigned alignment,
137 unsigned datasize, const uint64_t *fieldoffsets,
138 unsigned fieldcount);
140 // Constructor for C++ records.
141 typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
142 ASTRecordLayout(ASTContext &Ctx,
143 uint64_t size, unsigned alignment, uint64_t datasize,
144 const uint64_t *fieldoffsets, unsigned fieldcount,
145 uint64_t nonvirtualsize, unsigned nonvirtualalign,
146 uint64_t SizeOfLargestEmptySubobject,
147 const CXXRecordDecl *PrimaryBase,
148 bool PrimaryBaseIsVirtual,
149 const BaseOffsetsMapTy& BaseOffsets,
150 const BaseOffsetsMapTy& VBaseOffsets);
152 ~ASTRecordLayout() {}
154 void Destroy(ASTContext &Ctx);
156 ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT
157 void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT
160 /// getAlignment - Get the record alignment in bits.
161 unsigned getAlignment() const { return Alignment; }
163 /// getSize - Get the record size in bits.
164 uint64_t getSize() const { return Size; }
166 /// getFieldCount - Get the number of fields in the layout.
167 unsigned getFieldCount() const { return FieldCount; }
169 /// getFieldOffset - Get the offset of the given field index, in
171 uint64_t getFieldOffset(unsigned FieldNo) const {
172 assert (FieldNo < FieldCount && "Invalid Field No");
173 return FieldOffsets[FieldNo];
176 /// getDataSize() - Get the record data size, which is the record size
177 /// without tail padding, in bits.
178 uint64_t getDataSize() const {
182 /// getNonVirtualSize - Get the non-virtual size (in bits) of an object,
183 /// which is the size of the object without virtual bases.
184 uint64_t getNonVirtualSize() const {
185 assert(CXXInfo && "Record layout does not have C++ specific info!");
187 return CXXInfo->NonVirtualSize;
190 /// getNonVirtualSize - Get the non-virtual alignment (in bits) of an object,
191 /// which is the alignment of the object without virtual bases.
192 unsigned getNonVirtualAlign() const {
193 assert(CXXInfo && "Record layout does not have C++ specific info!");
195 return CXXInfo->NonVirtualAlign;
198 /// getPrimaryBaseInfo - Get the primary base info.
199 const PrimaryBaseInfo &getPrimaryBaseInfo() const {
200 assert(CXXInfo && "Record layout does not have C++ specific info!");
202 return CXXInfo->PrimaryBase;
205 // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
206 const CXXRecordDecl *getPrimaryBase() const {
207 return getPrimaryBaseInfo().getBase();
210 // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly.
211 bool getPrimaryBaseWasVirtual() const {
212 return getPrimaryBaseInfo().isVirtual();
215 /// getBaseClassOffset - Get the offset, in bits, for the given base class.
216 uint64_t getBaseClassOffset(const CXXRecordDecl *Base) const {
217 assert(CXXInfo && "Record layout does not have C++ specific info!");
218 assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!");
220 return CXXInfo->BaseOffsets[Base];
223 /// getVBaseClassOffset - Get the offset, in bits, for the given base class.
224 uint64_t getVBaseClassOffset(const CXXRecordDecl *VBase) const {
225 assert(CXXInfo && "Record layout does not have C++ specific info!");
226 assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!");
228 return CXXInfo->VBaseOffsets[VBase];
231 uint64_t getSizeOfLargestEmptySubobject() const {
232 assert(CXXInfo && "Record layout does not have C++ specific info!");
233 return CXXInfo->SizeOfLargestEmptySubobject;
236 primary_base_info_iterator primary_base_begin() const {
237 assert(CXXInfo && "Record layout does not have C++ specific info!");
239 return primary_base_info_iterator(getPrimaryBaseInfo());
242 primary_base_info_iterator primary_base_end() const {
243 assert(CXXInfo && "Record layout does not have C++ specific info!");
245 return primary_base_info_iterator();
249 } // end namespace clang