1 //=== ASTRecordLayoutBuilder.cpp - Helper class for building record layouts ==//
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 #include "RecordLayoutBuilder.h"
11 
12 #include "clang/AST/Attr.h"
13 #include "clang/AST/Decl.h"
14 #include "clang/AST/DeclCXX.h"
15 #include "clang/AST/DeclObjC.h"
16 #include "clang/AST/Expr.h"
17 #include "clang/AST/RecordLayout.h"
18 #include "clang/Basic/TargetInfo.h"
19 #include <llvm/Support/MathExtras.h>
20 
21 using namespace clang;
22 
23 ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
24   : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0),
25   IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8) {}
26 
27 void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
28   if (RD->isPolymorphic() || RD->getNumVBases())
29     {
30       // assert (RD->getNumBases() == 0 && "no polymorphic inheritance yet");
31       int AS = 0;
32       UpdateAlignment(Ctx.Target.getPointerAlign(AS));
33       Size += Ctx.Target.getPointerWidth(AS);
34       NextOffset = Size;
35     }
36 }
37 
38 void
39 ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
40   for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
41        e = RD->bases_end(); i != e; ++i) {
42     if (!i->isVirtual()) {
43       const CXXRecordDecl *Base =
44         cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
45       LayoutNonVirtualBase(Base);
46     }
47   }
48 }
49 
50 void ASTRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) {
51   const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD);
52     assert(BaseInfo.getDataSize() > 0 &&
53            "FIXME: Handle empty classes.");
54 
55   unsigned BaseAlign = BaseInfo.getNonVirtualAlign();
56   uint64_t BaseSize = BaseInfo.getNonVirtualSize();
57 
58   // Round up the current record size to the base's alignment boundary.
59   Size = (Size + (BaseAlign-1)) & ~(BaseAlign-1);
60 
61   // Add base class offsets.
62   Bases.push_back(RD);
63   BaseOffsets.push_back(Size);
64 
65   // Reserve space for this base.
66   Size += BaseSize;
67 
68   // Remember the next available offset.
69   NextOffset = Size;
70 
71   // Remember max struct/class alignment.
72   UpdateAlignment(BaseAlign);
73 }
74 
75 void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
76   IsUnion = D->isUnion();
77 
78   if (const PackedAttr* PA = D->getAttr<PackedAttr>())
79     StructPacking = PA->getAlignment();
80 
81   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
82     UpdateAlignment(AA->getAlignment());
83 
84   // If this is a C++ class, lay out the nonvirtual bases.
85   if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
86     LayoutVtable(RD);
87     LayoutNonVirtualBases(RD);
88 
89     assert (RD->getNumVBases() == 0
90             && "FIXME: We don't support virtual bases yet!");
91     // FIXME: We need to layout the virtual bases in the complete object layout.
92   }
93 
94   LayoutFields(D);
95 
96   NonVirtualSize = Size;
97   NonVirtualAlignment = Alignment;
98 
99   // Finally, round the size of the total struct up to the alignment of the
100   // struct itself.
101   FinishLayout();
102 }
103 
104 void ASTRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D,
105                                     const ObjCImplementationDecl *Impl) {
106   if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
107     const ASTRecordLayout &SL = Ctx.getASTObjCInterfaceLayout(SD);
108 
109     UpdateAlignment(SL.getAlignment());
110 
111     // We start laying out ivars not at the end of the superclass
112     // structure, but at the next byte following the last field.
113     Size = llvm::RoundUpToAlignment(SL.getDataSize(), 8);
114     NextOffset = Size;
115   }
116 
117   if (const PackedAttr *PA = D->getAttr<PackedAttr>())
118     StructPacking = PA->getAlignment();
119 
120   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
121     UpdateAlignment(AA->getAlignment());
122 
123   // Layout each ivar sequentially.
124   llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
125   Ctx.ShallowCollectObjCIvars(D, Ivars, Impl);
126   for (unsigned i = 0, e = Ivars.size(); i != e; ++i)
127     LayoutField(Ivars[i]);
128 
129   // Finally, round the size of the total struct up to the alignment of the
130   // struct itself.
131   FinishLayout();
132 }
133 
134 void ASTRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
135   // Layout each field, for now, just sequentially, respecting alignment.  In
136   // the future, this will need to be tweakable by targets.
137   for (RecordDecl::field_iterator Field = D->field_begin(),
138        FieldEnd = D->field_end(); Field != FieldEnd; ++Field)
139     LayoutField(*Field);
140 }
141 
142 void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
143   unsigned FieldPacking = StructPacking;
144   uint64_t FieldOffset = IsUnion ? 0 : Size;
145   uint64_t FieldSize;
146   unsigned FieldAlign;
147 
148   // FIXME: Should this override struct packing? Probably we want to
149   // take the minimum?
150   if (const PackedAttr *PA = D->getAttr<PackedAttr>())
151     FieldPacking = PA->getAlignment();
152 
153   if (const Expr *BitWidthExpr = D->getBitWidth()) {
154     // TODO: Need to check this algorithm on other targets!
155     //       (tested on Linux-X86)
156     FieldSize = BitWidthExpr->EvaluateAsInt(Ctx).getZExtValue();
157 
158     std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
159     uint64_t TypeSize = FieldInfo.first;
160 
161     // Determine the alignment of this bitfield. The packing
162     // attributes define a maximum and the alignment attribute defines
163     // a minimum.
164     // FIXME: What is the right behavior when the specified alignment
165     // is smaller than the specified packing?
166     FieldAlign = FieldInfo.second;
167     if (FieldPacking)
168       FieldAlign = std::min(FieldAlign, FieldPacking);
169     if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
170       FieldAlign = std::max(FieldAlign, AA->getAlignment());
171 
172     // Check if we need to add padding to give the field the correct
173     // alignment.
174     if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
175       FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
176 
177     // Padding members don't affect overall alignment
178     if (!D->getIdentifier())
179       FieldAlign = 1;
180   } else {
181     if (D->getType()->isIncompleteArrayType()) {
182       // This is a flexible array member; we can't directly
183       // query getTypeInfo about these, so we figure it out here.
184       // Flexible array members don't have any size, but they
185       // have to be aligned appropriately for their element type.
186       FieldSize = 0;
187       const ArrayType* ATy = Ctx.getAsArrayType(D->getType());
188       FieldAlign = Ctx.getTypeAlign(ATy->getElementType());
189     } else if (const ReferenceType *RT = D->getType()->getAs<ReferenceType>()) {
190       unsigned AS = RT->getPointeeType().getAddressSpace();
191       FieldSize = Ctx.Target.getPointerWidth(AS);
192       FieldAlign = Ctx.Target.getPointerAlign(AS);
193     } else {
194       std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
195       FieldSize = FieldInfo.first;
196       FieldAlign = FieldInfo.second;
197     }
198 
199     // Determine the alignment of this bitfield. The packing
200     // attributes define a maximum and the alignment attribute defines
201     // a minimum. Additionally, the packing alignment must be at least
202     // a byte for non-bitfields.
203     //
204     // FIXME: What is the right behavior when the specified alignment
205     // is smaller than the specified packing?
206     if (FieldPacking)
207       FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking));
208     if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
209       FieldAlign = std::max(FieldAlign, AA->getAlignment());
210 
211     // Round up the current record size to the field's alignment boundary.
212     FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
213   }
214 
215   // Place this field at the current location.
216   FieldOffsets.push_back(FieldOffset);
217 
218   // Reserve space for this field.
219   if (IsUnion)
220     Size = std::max(Size, FieldSize);
221   else
222     Size = FieldOffset + FieldSize;
223 
224   // Remember the next available offset.
225   NextOffset = Size;
226 
227   // Remember max struct/class alignment.
228   UpdateAlignment(FieldAlign);
229 }
230 
231 void ASTRecordLayoutBuilder::FinishLayout() {
232   // In C++, records cannot be of size 0.
233   if (Ctx.getLangOptions().CPlusPlus && Size == 0)
234     Size = 8;
235   // Finally, round the size of the record up to the alignment of the
236   // record itself.
237   Size = (Size + (Alignment-1)) & ~(Alignment-1);
238 }
239 
240 void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
241   if (NewAlignment <= Alignment)
242     return;
243 
244   assert(llvm::isPowerOf2_32(NewAlignment && "Alignment not a power of 2"));
245 
246   Alignment = NewAlignment;
247 }
248 
249 const ASTRecordLayout *
250 ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
251                                       const RecordDecl *D) {
252   ASTRecordLayoutBuilder Builder(Ctx);
253 
254   Builder.Layout(D);
255 
256   if (!isa<CXXRecordDecl>(D))
257     return new ASTRecordLayout(Builder.Size, Builder.Alignment, Builder.Size,
258                                Builder.FieldOffsets.data(),
259                                Builder.FieldOffsets.size());
260 
261   // FIXME: This is not always correct. See the part about bitfields at
262   // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
263   // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
264   bool IsPODForThePurposeOfLayout = cast<CXXRecordDecl>(D)->isPOD();
265 
266   assert(Builder.Bases.size() == Builder.BaseOffsets.size() &&
267          "Base offsets vector must be same size as bases vector!");
268 
269   // FIXME: This should be done in FinalizeLayout.
270   uint64_t DataSize =
271     IsPODForThePurposeOfLayout ? Builder.Size : Builder.NextOffset;
272   uint64_t NonVirtualSize =
273     IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
274 
275   return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize,
276                              Builder.FieldOffsets.data(),
277                              Builder.FieldOffsets.size(),
278                              NonVirtualSize,
279                              Builder.NonVirtualAlignment,
280                              Builder.Bases.data(),
281                              Builder.BaseOffsets.data(),
282                              Builder.Bases.size());
283 }
284 
285 const ASTRecordLayout *
286 ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
287                                       const ObjCInterfaceDecl *D,
288                                       const ObjCImplementationDecl *Impl) {
289   ASTRecordLayoutBuilder Builder(Ctx);
290 
291   Builder.Layout(D, Impl);
292 
293   return new ASTRecordLayout(Builder.Size, Builder.Alignment,
294                              Builder.NextOffset,
295                              Builder.FieldOffsets.data(),
296                              Builder.FieldOffsets.size());
297 }
298