1 //===- ASTRecordLayoutBuilder.h - Helper class for building record layouts ===//
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 #ifndef LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
11 #define LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/ADT/SmallSet.h"
15 #include "llvm/System/DataTypes.h"
20 class ASTRecordLayout;
23 class ObjCImplementationDecl;
24 class ObjCInterfaceDecl;
27 class ASTRecordLayoutBuilder {
32 llvm::SmallVector<uint64_t, 16> FieldOffsets;
34 /// Packed - Whether the record is packed or not.
37 /// MaxFieldAlignment - The maximum allowed field alignment. This is set by
39 unsigned MaxFieldAlignment;
41 /// DataSize - The data size of the record being laid out.
46 uint64_t NonVirtualSize;
47 unsigned NonVirtualAlignment;
48 const CXXRecordDecl *PrimaryBase;
49 bool PrimaryBaseWasVirtual;
51 typedef llvm::SmallVector<std::pair<const CXXRecordDecl *,
52 uint64_t>, 4> BaseOffsetsTy;
54 /// Bases - base classes and their offsets from the record.
57 // VBases - virtual base classes and their offsets from the record.
60 /// IndirectPrimaryBases - Virtual base classes, direct or indirect, that are
61 /// primary base classes for some other direct or indirect base class.
62 llvm::SmallSet<const CXXRecordDecl*, 32> IndirectPrimaryBases;
64 /// EmptyClassOffsets - A map from offsets to empty record decls.
65 typedef std::multimap<uint64_t, const CXXRecordDecl *> EmptyClassOffsetsTy;
66 EmptyClassOffsetsTy EmptyClassOffsets;
68 ASTRecordLayoutBuilder(ASTContext &Ctx);
70 void Layout(const RecordDecl *D);
71 void Layout(const CXXRecordDecl *D);
72 void Layout(const ObjCInterfaceDecl *D,
73 const ObjCImplementationDecl *Impl);
75 void LayoutFields(const RecordDecl *D);
76 void LayoutField(const FieldDecl *D);
78 void SelectPrimaryBase(const CXXRecordDecl *RD);
79 void SelectPrimaryVBase(const CXXRecordDecl *RD,
80 const CXXRecordDecl *&FirstPrimary);
82 /// IdentifyPrimaryBases - Identify all virtual base classes, direct or
83 /// indirect, that are primary base classes for some other direct or indirect
85 void IdentifyPrimaryBases(const CXXRecordDecl *RD);
87 void setPrimaryBase(const CXXRecordDecl *PB, bool Virtual) {
89 PrimaryBaseWasVirtual = Virtual;
92 bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
94 /// LayoutBase - Will lay out a base and return the offset where it was
96 uint64_t LayoutBase(const CXXRecordDecl *RD);
98 void LayoutVtable(const CXXRecordDecl *RD);
99 void LayoutNonVirtualBases(const CXXRecordDecl *RD);
100 void LayoutBaseNonVirtually(const CXXRecordDecl *RD, bool IsVBase);
101 void LayoutVirtualBase(const CXXRecordDecl *RD);
102 void LayoutVirtualBases(const CXXRecordDecl *Class, const CXXRecordDecl *RD,
103 const CXXRecordDecl *PB, uint64_t Offset,
104 llvm::SmallSet<const CXXRecordDecl*, 32> &mark,
105 llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary);
107 /// canPlaceRecordAtOffset - Return whether a record (either a base class
108 /// or a field) can be placed at the given offset.
109 /// Returns false if placing the record will result in two components
110 /// (direct or indirect) of the same type having the same offset.
111 bool canPlaceRecordAtOffset(const CXXRecordDecl *RD, uint64_t Offset) const;
113 /// canPlaceFieldAtOffset - Return whether a field can be placed at the given
115 bool canPlaceFieldAtOffset(const FieldDecl *FD, uint64_t Offset) const;
117 /// UpdateEmptyClassOffsets - Called after a record (either a base class
118 /// or a field) has been placed at the given offset. Will update the
119 /// EmptyClassOffsets map if the class is empty or has any empty bases or
121 void UpdateEmptyClassOffsets(const CXXRecordDecl *RD, uint64_t Offset);
123 /// UpdateEmptyClassOffsets - Called after a field has been placed at the
125 void UpdateEmptyClassOffsets(const FieldDecl *FD, uint64_t Offset);
127 /// getBaseOffset - Get the offset of a direct base class.
128 uint64_t getBaseOffset(const CXXRecordDecl *Base);
130 /// FinishLayout - Finalize record layout. Adjust record size based on the
134 void UpdateAlignment(unsigned NewAlignment);
136 ASTRecordLayoutBuilder(const ASTRecordLayoutBuilder&); // DO NOT IMPLEMENT
137 void operator=(const ASTRecordLayoutBuilder&); // DO NOT IMPLEMENT
139 static const ASTRecordLayout *ComputeLayout(ASTContext &Ctx,
140 const RecordDecl *RD);
141 static const ASTRecordLayout *ComputeLayout(ASTContext &Ctx,
142 const ObjCInterfaceDecl *D,
143 const ObjCImplementationDecl *Impl);
146 } // end namespace clang