1*67e74705SXin Li //===--- LayoutOverrideSource.cpp --Override Record Layouts ---------------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li #include "clang/Frontend/LayoutOverrideSource.h"
10*67e74705SXin Li #include "clang/AST/Decl.h"
11*67e74705SXin Li #include "clang/Basic/CharInfo.h"
12*67e74705SXin Li #include "llvm/Support/raw_ostream.h"
13*67e74705SXin Li #include <fstream>
14*67e74705SXin Li #include <string>
15*67e74705SXin Li
16*67e74705SXin Li using namespace clang;
17*67e74705SXin Li
18*67e74705SXin Li /// \brief Parse a simple identifier.
parseName(StringRef S)19*67e74705SXin Li static std::string parseName(StringRef S) {
20*67e74705SXin Li if (S.empty() || !isIdentifierHead(S[0]))
21*67e74705SXin Li return "";
22*67e74705SXin Li
23*67e74705SXin Li unsigned Offset = 1;
24*67e74705SXin Li while (Offset < S.size() && isIdentifierBody(S[Offset]))
25*67e74705SXin Li ++Offset;
26*67e74705SXin Li
27*67e74705SXin Li return S.substr(0, Offset).str();
28*67e74705SXin Li }
29*67e74705SXin Li
LayoutOverrideSource(StringRef Filename)30*67e74705SXin Li LayoutOverrideSource::LayoutOverrideSource(StringRef Filename) {
31*67e74705SXin Li std::ifstream Input(Filename.str().c_str());
32*67e74705SXin Li if (!Input.is_open())
33*67e74705SXin Li return;
34*67e74705SXin Li
35*67e74705SXin Li // Parse the output of -fdump-record-layouts.
36*67e74705SXin Li std::string CurrentType;
37*67e74705SXin Li Layout CurrentLayout;
38*67e74705SXin Li bool ExpectingType = false;
39*67e74705SXin Li
40*67e74705SXin Li while (Input.good()) {
41*67e74705SXin Li std::string Line;
42*67e74705SXin Li getline(Input, Line);
43*67e74705SXin Li
44*67e74705SXin Li StringRef LineStr(Line);
45*67e74705SXin Li
46*67e74705SXin Li // Determine whether the following line will start a
47*67e74705SXin Li if (LineStr.find("*** Dumping AST Record Layout") != StringRef::npos) {
48*67e74705SXin Li // Flush the last type/layout, if there is one.
49*67e74705SXin Li if (!CurrentType.empty())
50*67e74705SXin Li Layouts[CurrentType] = CurrentLayout;
51*67e74705SXin Li CurrentLayout = Layout();
52*67e74705SXin Li
53*67e74705SXin Li ExpectingType = true;
54*67e74705SXin Li continue;
55*67e74705SXin Li }
56*67e74705SXin Li
57*67e74705SXin Li // If we're expecting a type, grab it.
58*67e74705SXin Li if (ExpectingType) {
59*67e74705SXin Li ExpectingType = false;
60*67e74705SXin Li
61*67e74705SXin Li StringRef::size_type Pos;
62*67e74705SXin Li if ((Pos = LineStr.find("struct ")) != StringRef::npos)
63*67e74705SXin Li LineStr = LineStr.substr(Pos + strlen("struct "));
64*67e74705SXin Li else if ((Pos = LineStr.find("class ")) != StringRef::npos)
65*67e74705SXin Li LineStr = LineStr.substr(Pos + strlen("class "));
66*67e74705SXin Li else if ((Pos = LineStr.find("union ")) != StringRef::npos)
67*67e74705SXin Li LineStr = LineStr.substr(Pos + strlen("union "));
68*67e74705SXin Li else
69*67e74705SXin Li continue;
70*67e74705SXin Li
71*67e74705SXin Li // Find the name of the type.
72*67e74705SXin Li CurrentType = parseName(LineStr);
73*67e74705SXin Li CurrentLayout = Layout();
74*67e74705SXin Li continue;
75*67e74705SXin Li }
76*67e74705SXin Li
77*67e74705SXin Li // Check for the size of the type.
78*67e74705SXin Li StringRef::size_type Pos = LineStr.find(" Size:");
79*67e74705SXin Li if (Pos != StringRef::npos) {
80*67e74705SXin Li // Skip past the " Size:" prefix.
81*67e74705SXin Li LineStr = LineStr.substr(Pos + strlen(" Size:"));
82*67e74705SXin Li
83*67e74705SXin Li unsigned long long Size = 0;
84*67e74705SXin Li (void)LineStr.getAsInteger(10, Size);
85*67e74705SXin Li CurrentLayout.Size = Size;
86*67e74705SXin Li continue;
87*67e74705SXin Li }
88*67e74705SXin Li
89*67e74705SXin Li // Check for the alignment of the type.
90*67e74705SXin Li Pos = LineStr.find("Alignment:");
91*67e74705SXin Li if (Pos != StringRef::npos) {
92*67e74705SXin Li // Skip past the "Alignment:" prefix.
93*67e74705SXin Li LineStr = LineStr.substr(Pos + strlen("Alignment:"));
94*67e74705SXin Li
95*67e74705SXin Li unsigned long long Alignment = 0;
96*67e74705SXin Li (void)LineStr.getAsInteger(10, Alignment);
97*67e74705SXin Li CurrentLayout.Align = Alignment;
98*67e74705SXin Li continue;
99*67e74705SXin Li }
100*67e74705SXin Li
101*67e74705SXin Li // Check for the size/alignment of the type.
102*67e74705SXin Li Pos = LineStr.find("sizeof=");
103*67e74705SXin Li if (Pos != StringRef::npos) {
104*67e74705SXin Li /* Skip past the sizeof= prefix. */
105*67e74705SXin Li LineStr = LineStr.substr(Pos + strlen("sizeof="));
106*67e74705SXin Li
107*67e74705SXin Li // Parse size.
108*67e74705SXin Li unsigned long long Size = 0;
109*67e74705SXin Li (void)LineStr.getAsInteger(10, Size);
110*67e74705SXin Li CurrentLayout.Size = Size;
111*67e74705SXin Li
112*67e74705SXin Li Pos = LineStr.find("align=");
113*67e74705SXin Li if (Pos != StringRef::npos) {
114*67e74705SXin Li /* Skip past the align= prefix. */
115*67e74705SXin Li LineStr = LineStr.substr(Pos + strlen("align="));
116*67e74705SXin Li
117*67e74705SXin Li // Parse alignment.
118*67e74705SXin Li unsigned long long Alignment = 0;
119*67e74705SXin Li (void)LineStr.getAsInteger(10, Alignment);
120*67e74705SXin Li CurrentLayout.Align = Alignment;
121*67e74705SXin Li }
122*67e74705SXin Li
123*67e74705SXin Li continue;
124*67e74705SXin Li }
125*67e74705SXin Li
126*67e74705SXin Li // Check for the field offsets of the type.
127*67e74705SXin Li Pos = LineStr.find("FieldOffsets: [");
128*67e74705SXin Li if (Pos == StringRef::npos)
129*67e74705SXin Li continue;
130*67e74705SXin Li
131*67e74705SXin Li LineStr = LineStr.substr(Pos + strlen("FieldOffsets: ["));
132*67e74705SXin Li while (!LineStr.empty() && isDigit(LineStr[0])) {
133*67e74705SXin Li // Parse this offset.
134*67e74705SXin Li unsigned Idx = 1;
135*67e74705SXin Li while (Idx < LineStr.size() && isDigit(LineStr[Idx]))
136*67e74705SXin Li ++Idx;
137*67e74705SXin Li
138*67e74705SXin Li unsigned long long Offset = 0;
139*67e74705SXin Li (void)LineStr.substr(0, Idx).getAsInteger(10, Offset);
140*67e74705SXin Li
141*67e74705SXin Li CurrentLayout.FieldOffsets.push_back(Offset);
142*67e74705SXin Li
143*67e74705SXin Li // Skip over this offset, the following comma, and any spaces.
144*67e74705SXin Li LineStr = LineStr.substr(Idx + 1);
145*67e74705SXin Li while (!LineStr.empty() && isWhitespace(LineStr[0]))
146*67e74705SXin Li LineStr = LineStr.substr(1);
147*67e74705SXin Li }
148*67e74705SXin Li }
149*67e74705SXin Li
150*67e74705SXin Li // Flush the last type/layout, if there is one.
151*67e74705SXin Li if (!CurrentType.empty())
152*67e74705SXin Li Layouts[CurrentType] = CurrentLayout;
153*67e74705SXin Li }
154*67e74705SXin Li
155*67e74705SXin Li bool
layoutRecordType(const RecordDecl * Record,uint64_t & Size,uint64_t & Alignment,llvm::DenseMap<const FieldDecl *,uint64_t> & FieldOffsets,llvm::DenseMap<const CXXRecordDecl *,CharUnits> & BaseOffsets,llvm::DenseMap<const CXXRecordDecl *,CharUnits> & VirtualBaseOffsets)156*67e74705SXin Li LayoutOverrideSource::layoutRecordType(const RecordDecl *Record,
157*67e74705SXin Li uint64_t &Size, uint64_t &Alignment,
158*67e74705SXin Li llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
159*67e74705SXin Li llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
160*67e74705SXin Li llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets)
161*67e74705SXin Li {
162*67e74705SXin Li // We can't override unnamed declarations.
163*67e74705SXin Li if (!Record->getIdentifier())
164*67e74705SXin Li return false;
165*67e74705SXin Li
166*67e74705SXin Li // Check whether we have a layout for this record.
167*67e74705SXin Li llvm::StringMap<Layout>::iterator Known = Layouts.find(Record->getName());
168*67e74705SXin Li if (Known == Layouts.end())
169*67e74705SXin Li return false;
170*67e74705SXin Li
171*67e74705SXin Li // Provide field layouts.
172*67e74705SXin Li unsigned NumFields = 0;
173*67e74705SXin Li for (RecordDecl::field_iterator F = Record->field_begin(),
174*67e74705SXin Li FEnd = Record->field_end();
175*67e74705SXin Li F != FEnd; ++F, ++NumFields) {
176*67e74705SXin Li if (NumFields >= Known->second.FieldOffsets.size())
177*67e74705SXin Li continue;
178*67e74705SXin Li
179*67e74705SXin Li FieldOffsets[*F] = Known->second.FieldOffsets[NumFields];
180*67e74705SXin Li }
181*67e74705SXin Li
182*67e74705SXin Li // Wrong number of fields.
183*67e74705SXin Li if (NumFields != Known->second.FieldOffsets.size())
184*67e74705SXin Li return false;
185*67e74705SXin Li
186*67e74705SXin Li Size = Known->second.Size;
187*67e74705SXin Li Alignment = Known->second.Align;
188*67e74705SXin Li return true;
189*67e74705SXin Li }
190*67e74705SXin Li
dump()191*67e74705SXin Li LLVM_DUMP_METHOD void LayoutOverrideSource::dump() {
192*67e74705SXin Li raw_ostream &OS = llvm::errs();
193*67e74705SXin Li for (llvm::StringMap<Layout>::iterator L = Layouts.begin(),
194*67e74705SXin Li LEnd = Layouts.end();
195*67e74705SXin Li L != LEnd; ++L) {
196*67e74705SXin Li OS << "Type: blah " << L->first() << '\n';
197*67e74705SXin Li OS << " Size:" << L->second.Size << '\n';
198*67e74705SXin Li OS << " Alignment:" << L->second.Align << '\n';
199*67e74705SXin Li OS << " FieldOffsets: [";
200*67e74705SXin Li for (unsigned I = 0, N = L->second.FieldOffsets.size(); I != N; ++I) {
201*67e74705SXin Li if (I)
202*67e74705SXin Li OS << ", ";
203*67e74705SXin Li OS << L->second.FieldOffsets[I];
204*67e74705SXin Li }
205*67e74705SXin Li OS << "]\n";
206*67e74705SXin Li }
207*67e74705SXin Li }
208*67e74705SXin Li
209