clang: lib/Frontend/LayoutOverrideSource.cpp Source File (original) (raw)

1

2

3

4

5

6

7

12#include "llvm/Support/raw_ostream.h"

13#include

14#include

15

16using namespace clang;

17

18

19static std::string parseName(StringRef S) {

21 return "";

22

23 unsigned Offset = 1;

25 ++Offset;

26

27 return S.substr(0, Offset).str();

28}

29

30

31static bool parseUnsigned(StringRef &S, unsigned long long &ULL) {

32 if (S.empty() || isDigit(S[0]))

33 return false;

34 unsigned Idx = 1;

35 while (Idx < S.size() && isDigit(S[Idx]))

36 ++Idx;

37 (void)S.substr(0, Idx).getAsInteger(10, ULL);

38 S = S.substr(Idx);

39 return true;

40}

41

43 std::ifstream Input(Filename.str().c_str());

44 if (!Input.is_open())

45 return;

46

47

48 std::string CurrentType;

49 Layout CurrentLayout;

50 bool ExpectingType = false;

51

52 while (Input.good()) {

53 std::string Line;

54 getline(Input, Line);

55

56 StringRef LineStr(Line);

57

58

59 if (LineStr.contains("*** Dumping AST Record Layout")) {

60

61 if (!CurrentType.empty())

62 Layouts[CurrentType] = CurrentLayout;

63 CurrentLayout = Layout();

64

65 ExpectingType = true;

66 continue;

67 }

68

69

70 if (ExpectingType) {

71 ExpectingType = false;

72

73 StringRef::size_type Pos;

74 if ((Pos = LineStr.find("struct ")) != StringRef::npos)

75 LineStr = LineStr.substr(Pos + strlen("struct "));

76 else if ((Pos = LineStr.find("class ")) != StringRef::npos)

77 LineStr = LineStr.substr(Pos + strlen("class "));

78 else if ((Pos = LineStr.find("union ")) != StringRef::npos)

79 LineStr = LineStr.substr(Pos + strlen("union "));

80 else

81 continue;

82

83

85 CurrentLayout = Layout();

86 continue;

87 }

88

89

90 StringRef::size_type Pos = LineStr.find(" Size:");

91 if (Pos != StringRef::npos) {

92

93 LineStr = LineStr.substr(Pos + strlen(" Size:"));

94

95 unsigned long long Size = 0;

97 CurrentLayout.Size = Size;

98 continue;

99 }

100

101

102 Pos = LineStr.find("Alignment:");

103 if (Pos != StringRef::npos) {

104

105 LineStr = LineStr.substr(Pos + strlen("Alignment:"));

106

107 unsigned long long Alignment = 0;

109 CurrentLayout.Align = Alignment;

110 continue;

111 }

112

113

114

115 Pos = LineStr.find("sizeof=");

116 if (Pos != StringRef::npos) {

117

118 LineStr = LineStr.substr(Pos + strlen("sizeof="));

119

120

121 unsigned long long Size = 0;

123 CurrentLayout.Size = Size * 8;

124

125 Pos = LineStr.find("align=");

126 if (Pos != StringRef::npos) {

127

128 LineStr = LineStr.substr(Pos + strlen("align="));

129

130

131 unsigned long long Alignment = 0;

133 CurrentLayout.Align = Alignment * 8;

134 }

135

136 continue;

137 }

138

139

140 Pos = LineStr.find("FieldOffsets: [");

141 if (Pos != StringRef::npos) {

142 LineStr = LineStr.substr(Pos + strlen("FieldOffsets: ["));

143 while (!LineStr.empty() && isDigit(LineStr[0])) {

144 unsigned long long Offset = 0;

146 CurrentLayout.FieldOffsets.push_back(Offset);

147

148

149 LineStr = LineStr.substr(1);

151 }

152 }

153

154

155 Pos = LineStr.find("VBaseOffsets: [");

156 if (Pos != StringRef::npos) {

157 LineStr = LineStr.substr(Pos + strlen("VBaseOffsets: ["));

158 while (!LineStr.empty() && isDigit(LineStr[0])) {

159 unsigned long long Offset = 0;

162

163

164 LineStr = LineStr.substr(1);

166 }

167 continue;

168 }

169

170

171 Pos = LineStr.find("BaseOffsets: [");

172 if (Pos != StringRef::npos) {

173 LineStr = LineStr.substr(Pos + strlen("BaseOffsets: ["));

174 while (!LineStr.empty() && isDigit(LineStr[0])) {

175 unsigned long long Offset = 0;

178

179

180 LineStr = LineStr.substr(1);

182 }

183 }

184 }

185

186

187 if (!CurrentType.empty())

188 Layouts[CurrentType] = CurrentLayout;

189}

190

191bool

193 uint64_t &Size, uint64_t &Alignment,

194 llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,

195 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,

196 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets)

197{

198

199 if (Record->getIdentifier())

200 return false;

201

202

203 llvm::StringMap::iterator Known = Layouts.find(Record->getName());

204 if (Known == Layouts.end())

205 return false;

206

207

208 unsigned NumFields = 0;

210 FEnd = Record->field_end();

211 F != FEnd; ++F, ++NumFields) {

212 if (NumFields >= Known->second.FieldOffsets.size())

213 continue;

214

215 FieldOffsets[*F] = Known->second.FieldOffsets[NumFields];

216 }

217

218

219 if (NumFields != Known->second.FieldOffsets.size())

220 return false;

221

222

223 if (const auto *RD = dyn_cast(Record)) {

224 unsigned NumNB = 0;

225 unsigned NumVB = 0;

226 for (const auto &I : RD->vbases()) {

227 if (NumVB >= Known->second.VBaseOffsets.size())

228 continue;

229 const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();

230 VirtualBaseOffsets[VBase] = Known->second.VBaseOffsets[NumVB++];

231 }

232 for (const auto &I : RD->bases()) {

233 if (I.isVirtual() || NumNB >= Known->second.BaseOffsets.size())

234 continue;

236 BaseOffsets[Base] = Known->second.BaseOffsets[NumNB++];

237 }

238 }

239

240 Size = Known->second.Size;

241 Alignment = Known->second.Align;

242 return true;

243}

244

246 raw_ostream &OS = llvm::errs();

247 for (llvm::StringMap::iterator L = Layouts.begin(),

248 LEnd = Layouts.end();

249 L != LEnd; ++L) {

250 OS << "Type: blah " << L->first() << '\n';

251 OS << " Size:" << L->second.Size << '\n';

252 OS << " Alignment:" << L->second.Align << '\n';

253 OS << " FieldOffsets: [";

254 for (unsigned I = 0, N = L->second.FieldOffsets.size(); I != N; ++I) {

255 if (I)

256 OS << ", ";

257 OS << L->second.FieldOffsets[I];

258 }

259 OS << "]\n";

260 }

261}

262

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

static bool parseUnsigned(StringRef &S, unsigned long long &ULL)

Parse an unsigned integer and move S to the next non-digit character.

static std::string parseName(StringRef S)

Parse a simple identifier.

llvm::MachO::Record Record

Represents a C++ struct/union/class.

static CharUnits fromQuantity(QuantityType Quantity)

fromQuantity - Construct a CharUnits quantity from a raw integer type.

specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...

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) override

If this particular record type has an overridden layout, return that layout.

void dump()

Dump the overridden layouts.

LayoutOverrideSource(StringRef Filename)

Create a new AST source that overrides the layout of some set of record types.

Represents a struct/union/class.

The JSON file list parser is used to communicate input to InstallAPI.

LLVM_READONLY bool isAsciiIdentifierContinue(unsigned char c)

LLVM_READONLY bool isDigit(unsigned char c)

Return true if this character is an ASCII digit: [0-9].

LLVM_READONLY bool isWhitespace(unsigned char c)

Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...

LLVM_READONLY bool isAsciiIdentifierStart(unsigned char c, bool AllowDollar=false)

Returns true if this is a valid first character of a C identifier, which is [a-zA-Z_].