blob: 27e1e027d0fa2bae53f76af0e8d8fc3bae3a4276 [file] [log] [blame]
Sean Hunt16171442010-06-16 23:45:50 +00001//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
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// These tablegen backends emit Clang attribute processing code
11//
12//===----------------------------------------------------------------------===//
13
14#include "ClangAttrEmitter.h"
15#include "Record.h"
Sean Hunt726a3d22010-08-18 23:23:09 +000016#include "llvm/ADT/StringSwitch.h"
Sean Hunt16171442010-06-16 23:45:50 +000017#include <algorithm>
Sean Hunt5c5f4662010-08-19 00:19:03 +000018#include <cctype>
Sean Hunt16171442010-06-16 23:45:50 +000019
20using namespace llvm;
21
Jim Grosbachbb168242010-10-08 18:13:57 +000022static const std::vector<StringRef>
23getValueAsListOfStrings(Record &R, StringRef FieldName) {
Sean Hunt726a3d22010-08-18 23:23:09 +000024 ListInit *List = R.getValueAsListInit(FieldName);
25 assert (List && "Got a null ListInit");
26
27 std::vector<StringRef> Strings;
28 Strings.reserve(List->getSize());
29
30 for (ListInit::iterator i = List->begin(), e = List->end(); i != e; ++i) {
31 assert(*i && "Got a null element in a ListInit");
32 if (StringInit *S = dynamic_cast<StringInit *>(*i))
33 Strings.push_back(S->getValue());
34 else if (CodeInit *C = dynamic_cast<CodeInit *>(*i))
35 Strings.push_back(C->getValue());
36 else
37 assert(false && "Got a non-string, non-code element in a ListInit");
38 }
39
40 return Strings;
41}
42
43std::string ReadPCHRecord(StringRef type) {
44 return StringSwitch<std::string>(type)
45 .EndsWith("Decl *", "cast_or_null<" + std::string(type, 0, type.size()-1) +
46 ">(GetDecl(Record[Idx++]))")
Douglas Gregor4a12f222010-10-05 14:51:48 +000047 .Case("QualType", "GetType(Record[Idx++])")
Sean Huntc85094f2011-02-17 03:30:09 +000048 .Case("Expr *", "ReadSubExpr()")
Sean Hunt726a3d22010-08-18 23:23:09 +000049 .Default("Record[Idx++]");
50}
51
52// Assumes that the way to get the value is SA->getname()
53std::string WritePCHRecord(StringRef type, StringRef name) {
54 return StringSwitch<std::string>(type)
55 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
56 ", Record);\n")
57 .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
Sean Huntc85094f2011-02-17 03:30:09 +000058 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
Sean Hunt726a3d22010-08-18 23:23:09 +000059 .Default("Record.push_back(" + std::string(name) + ");\n");
60}
61
62namespace {
63 class Argument {
64 std::string lowerName, upperName;
65 StringRef attrName;
66
67 public:
68 Argument(Record &Arg, StringRef Attr)
69 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
70 attrName(Attr) {
71 if (!lowerName.empty()) {
72 lowerName[0] = std::tolower(lowerName[0]);
73 upperName[0] = std::toupper(upperName[0]);
74 }
75 }
Chandler Carruth54f61632010-08-23 08:25:07 +000076 virtual ~Argument() {}
Sean Hunt726a3d22010-08-18 23:23:09 +000077
Sean Hunt5b385002010-08-19 00:03:05 +000078 StringRef getLowerName() const { return lowerName; }
79 StringRef getUpperName() const { return upperName; }
80 StringRef getAttrName() const { return attrName; }
Sean Hunt726a3d22010-08-18 23:23:09 +000081
82 // These functions print the argument contents formatted in different ways.
83 virtual void writeAccessors(raw_ostream &OS) const = 0;
84 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
85 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
86 virtual void writeCtorBody(raw_ostream &OS) const {}
87 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
88 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
89 virtual void writeDeclarations(raw_ostream &OS) const = 0;
90 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
91 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
92 virtual void writePCHWrite(raw_ostream &OS) const = 0;
93 };
94
95 class SimpleArgument : public Argument {
96 std::string type;
97
98 public:
99 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
100 : Argument(Arg, Attr), type(T)
101 {}
102
Sean Hunt726a3d22010-08-18 23:23:09 +0000103 void writeAccessors(raw_ostream &OS) const {
104 OS << " " << type << " get" << getUpperName() << "() const {\n";
105 OS << " return " << getLowerName() << ";\n";
106 OS << " }";
107 }
108 void writeCloneArgs(raw_ostream &OS) const {
109 OS << getLowerName();
110 }
111 void writeCtorInitializers(raw_ostream &OS) const {
112 OS << getLowerName() << "(" << getUpperName() << ")";
113 }
114 void writeCtorParameters(raw_ostream &OS) const {
115 OS << type << " " << getUpperName();
116 }
117 void writeDeclarations(raw_ostream &OS) const {
118 OS << type << " " << getLowerName() << ";";
119 }
120 void writePCHReadDecls(raw_ostream &OS) const {
121 std::string read = ReadPCHRecord(type);
122 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
123 }
124 void writePCHReadArgs(raw_ostream &OS) const {
125 OS << getLowerName();
126 }
127 void writePCHWrite(raw_ostream &OS) const {
128 OS << " " << WritePCHRecord(type, "SA->get" +
129 std::string(getUpperName()) + "()");
130 }
131 };
132
133 class StringArgument : public Argument {
134 public:
135 StringArgument(Record &Arg, StringRef Attr)
136 : Argument(Arg, Attr)
137 {}
138
139 void writeAccessors(raw_ostream &OS) const {
140 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
141 OS << " return llvm::StringRef(" << getLowerName() << ", "
142 << getLowerName() << "Length);\n";
143 OS << " }\n";
144 OS << " unsigned get" << getUpperName() << "Length() const {\n";
145 OS << " return " << getLowerName() << "Length;\n";
146 OS << " }\n";
147 OS << " void set" << getUpperName()
148 << "(ASTContext &C, llvm::StringRef S) {\n";
149 OS << " " << getLowerName() << "Length = S.size();\n";
150 OS << " this->" << getLowerName() << " = new (C, 1) char ["
151 << getLowerName() << "Length];\n";
152 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
153 << getLowerName() << "Length);\n";
154 OS << " }";
155 }
156 void writeCloneArgs(raw_ostream &OS) const {
157 OS << "get" << getUpperName() << "()";
158 }
159 void writeCtorBody(raw_ostream &OS) const {
160 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
161 << ".data(), " << getLowerName() << "Length);";
162 }
163 void writeCtorInitializers(raw_ostream &OS) const {
164 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
165 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
166 << "Length])";
167 }
168 void writeCtorParameters(raw_ostream &OS) const {
169 OS << "llvm::StringRef " << getUpperName();
170 }
171 void writeDeclarations(raw_ostream &OS) const {
172 OS << "unsigned " << getLowerName() << "Length;\n";
173 OS << "char *" << getLowerName() << ";";
174 }
175 void writePCHReadDecls(raw_ostream &OS) const {
Jim Grosbachbb168242010-10-08 18:13:57 +0000176 OS << " std::string " << getLowerName()
177 << "= ReadString(Record, Idx);\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000178 }
179 void writePCHReadArgs(raw_ostream &OS) const {
180 OS << getLowerName();
181 }
182 void writePCHWrite(raw_ostream &OS) const {
183 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
184 }
185 };
186
187 class AlignedArgument : public Argument {
188 public:
189 AlignedArgument(Record &Arg, StringRef Attr)
190 : Argument(Arg, Attr)
191 {}
192
193 void writeAccessors(raw_ostream &OS) const {
194 OS << " bool is" << getUpperName() << "Dependent() const;\n";
195
196 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
197
198 OS << " bool is" << getUpperName() << "Expr() const {\n";
199 OS << " return is" << getLowerName() << "Expr;\n";
200 OS << " }\n";
201
202 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
203 OS << " assert(is" << getLowerName() << "Expr);\n";
204 OS << " return " << getLowerName() << "Expr;\n";
205 OS << " }\n";
206
207 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
208 OS << " assert(!is" << getLowerName() << "Expr);\n";
209 OS << " return " << getLowerName() << "Type;\n";
210 OS << " }";
211 }
212 void writeAccessorDefinitions(raw_ostream &OS) const {
213 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
214 << "Dependent() const {\n";
215 OS << " if (is" << getLowerName() << "Expr)\n";
216 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
217 << "Expr->isValueDependent() || " << getLowerName()
218 << "Expr->isTypeDependent());\n";
219 OS << " else\n";
220 OS << " return " << getLowerName()
221 << "Type->getType()->isDependentType();\n";
222 OS << "}\n";
223
224 // FIXME: Do not do the calculation here
225 // FIXME: Handle types correctly
226 // A null pointer means maximum alignment
227 // FIXME: Load the platform-specific maximum alignment, rather than
228 // 16, the x86 max.
229 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
230 << "(ASTContext &Ctx) const {\n";
231 OS << " assert(!is" << getUpperName() << "Dependent());\n";
232 OS << " if (is" << getLowerName() << "Expr)\n";
233 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
234 << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)"
235 << "* Ctx.getCharWidth();\n";
236 OS << " else\n";
237 OS << " return 0; // FIXME\n";
238 OS << "}\n";
239 }
240 void writeCloneArgs(raw_ostream &OS) const {
241 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
242 << "Expr ? static_cast<void*>(" << getLowerName()
243 << "Expr) : " << getLowerName()
244 << "Type";
245 }
246 void writeCtorBody(raw_ostream &OS) const {
247 OS << " if (is" << getLowerName() << "Expr)\n";
248 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
249 << getUpperName() << ");\n";
250 OS << " else\n";
251 OS << " " << getLowerName()
252 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
253 << ");";
254 }
255 void writeCtorInitializers(raw_ostream &OS) const {
256 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
257 }
258 void writeCtorParameters(raw_ostream &OS) const {
259 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
260 }
261 void writeDeclarations(raw_ostream &OS) const {
262 OS << "bool is" << getLowerName() << "Expr;\n";
263 OS << "union {\n";
264 OS << "Expr *" << getLowerName() << "Expr;\n";
265 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
266 OS << "};";
267 }
268 void writePCHReadArgs(raw_ostream &OS) const {
269 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
270 }
271 void writePCHReadDecls(raw_ostream &OS) const {
272 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
273 OS << " void *" << getLowerName() << "Ptr;\n";
274 OS << " if (is" << getLowerName() << "Expr)\n";
Sebastian Redl2dc91642010-10-05 15:59:36 +0000275 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000276 OS << " else\n";
277 OS << " " << getLowerName()
Sebastian Redl2dc91642010-10-05 15:59:36 +0000278 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000279 }
280 void writePCHWrite(raw_ostream &OS) const {
281 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
282 OS << " if (SA->is" << getUpperName() << "Expr())\n";
283 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
284 OS << " else\n";
285 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
286 << "Type(), Record);\n";
287 }
288 };
289
290 class VariadicArgument : public Argument {
291 std::string type;
292
293 public:
294 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
295 : Argument(Arg, Attr), type(T)
296 {}
297
298 std::string getType() const { return type; }
299
300 void writeAccessors(raw_ostream &OS) const {
301 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
302 OS << " " << getLowerName() << "_iterator " << getLowerName()
303 << "_begin() const {\n";
304 OS << " return " << getLowerName() << ";\n";
305 OS << " }\n";
306 OS << " " << getLowerName() << "_iterator " << getLowerName()
307 << "_end() const {\n";
308 OS << " return " << getLowerName() << " + " << getLowerName()
309 << "Size;\n";
310 OS << " }\n";
311 OS << " unsigned " << getLowerName() << "_size() const {\n"
312 << " return " << getLowerName() << "Size;\n;";
313 OS << " }";
314 }
315 void writeCloneArgs(raw_ostream &OS) const {
316 OS << getLowerName() << ", " << getLowerName() << "Size";
317 }
318 void writeCtorBody(raw_ostream &OS) const {
319 // FIXME: memcpy is not safe on non-trivial types.
320 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
321 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
322 }
323 void writeCtorInitializers(raw_ostream &OS) const {
324 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
325 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
326 << getLowerName() << "Size])";
327 }
328 void writeCtorParameters(raw_ostream &OS) const {
329 OS << getType() << " *" << getUpperName() << ", unsigned "
330 << getUpperName() << "Size";
331 }
332 void writeDeclarations(raw_ostream &OS) const {
333 OS << " unsigned " << getLowerName() << "Size;\n";
334 OS << " " << getType() << " *" << getLowerName() << ";";
335 }
336 void writePCHReadDecls(raw_ostream &OS) const {
337 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
338 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
339 << ";\n";
340 OS << " " << getLowerName() << ".reserve(" << getLowerName()
341 << "Size);\n";
342 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
343
344 std::string read = ReadPCHRecord(type);
345 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
346 }
347 void writePCHReadArgs(raw_ostream &OS) const {
348 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
349 }
350 void writePCHWrite(raw_ostream &OS) const{
351 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
352 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
353 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
354 << getLowerName() << "_end(); i != e; ++i)\n";
355 OS << " " << WritePCHRecord(type, "(*i)");
356 }
357 };
358
359 class EnumArgument : public Argument {
Eli Friedmana8fa3922010-08-19 06:11:05 +0000360 std::string type;
Sean Hunt726a3d22010-08-18 23:23:09 +0000361 std::vector<StringRef> values, enums;
362 public:
363 EnumArgument(Record &Arg, StringRef Attr)
364 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
365 values(getValueAsListOfStrings(Arg, "Values")),
366 enums(getValueAsListOfStrings(Arg, "Enums"))
367 {}
368
369 void writeAccessors(raw_ostream &OS) const {
370 OS << " " << type << " get" << getUpperName() << "() const {\n";
371 OS << " return " << getLowerName() << ";\n";
372 OS << " }";
373 }
374 void writeCloneArgs(raw_ostream &OS) const {
375 OS << getLowerName();
376 }
377 void writeCtorInitializers(raw_ostream &OS) const {
378 OS << getLowerName() << "(" << getUpperName() << ")";
379 }
380 void writeCtorParameters(raw_ostream &OS) const {
381 OS << type << " " << getUpperName();
382 }
383 void writeDeclarations(raw_ostream &OS) const {
384 // Calculate the various enum values
385 std::vector<StringRef> uniques(enums);
386 std::sort(uniques.begin(), uniques.end());
387 uniques.erase(std::unique(uniques.begin(), uniques.end()),
388 uniques.end());
389 // FIXME: Emit a proper error
390 assert(!uniques.empty());
391
392 std::vector<StringRef>::iterator i = uniques.begin(),
393 e = uniques.end();
394 // The last one needs to not have a comma.
395 --e;
396
397 OS << "public:\n";
398 OS << " enum " << type << " {\n";
399 for (; i != e; ++i)
400 OS << " " << *i << ",\n";
401 OS << " " << *e << "\n";
402 OS << " };\n";
403 OS << "private:\n";
404 OS << " " << type << " " << getLowerName() << ";";
405 }
406 void writePCHReadDecls(raw_ostream &OS) const {
407 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
408 << "(static_cast<" << getAttrName() << "Attr::" << type
409 << ">(Record[Idx++]));\n";
410 }
411 void writePCHReadArgs(raw_ostream &OS) const {
412 OS << getLowerName();
413 }
414 void writePCHWrite(raw_ostream &OS) const {
415 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
416 }
417 };
418}
419
420static Argument *createArgument(Record &Arg, StringRef Attr,
421 Record *Search = 0) {
422 if (!Search)
423 Search = &Arg;
424
425 Argument *Ptr = 0;
426 llvm::StringRef ArgName = Search->getName();
427
428 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
429 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
430 else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
431 "Expr *");
432 else if (ArgName == "FunctionArgument")
433 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
434 else if (ArgName == "IdentifierArgument")
435 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
436 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
437 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
438 else if (ArgName == "TypeArgument")
439 Ptr = new SimpleArgument(Arg, Attr, "QualType");
440 else if (ArgName == "UnsignedArgument")
441 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
442 else if (ArgName == "VariadicUnsignedArgument")
443 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
444
445 if (!Ptr) {
446 std::vector<Record*> Bases = Search->getSuperClasses();
447 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
448 i != e; ++i) {
449 Ptr = createArgument(Arg, Attr, *i);
450 if (Ptr)
451 break;
452 }
453 }
454 return Ptr;
455}
456
Sean Hunt16171442010-06-16 23:45:50 +0000457void ClangAttrClassEmitter::run(raw_ostream &OS) {
458 OS << "// This file is generated by TableGen. Do not edit.\n\n";
459 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
460 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
461
462 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
463
464 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
465 i != e; ++i) {
466 Record &R = **i;
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000467 const std::string &SuperName = R.getSuperClasses().back()->getName();
Sean Hunt16171442010-06-16 23:45:50 +0000468
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000469 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
Sean Hunt16171442010-06-16 23:45:50 +0000470
Sean Hunt726a3d22010-08-18 23:23:09 +0000471 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
472 std::vector<Argument*> Args;
473 std::vector<Argument*>::iterator ai, ae;
474 Args.reserve(ArgRecords.size());
Sean Hunt16171442010-06-16 23:45:50 +0000475
Sean Hunt726a3d22010-08-18 23:23:09 +0000476 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
477 re = ArgRecords.end();
478 ri != re; ++ri) {
479 Record &ArgRecord = **ri;
480 Argument *Arg = createArgument(ArgRecord, R.getName());
481 assert(Arg);
482 Args.push_back(Arg);
483
484 Arg->writeDeclarations(OS);
485 OS << "\n\n";
486 }
487
488 ae = Args.end();
Sean Hunt16171442010-06-16 23:45:50 +0000489
490 OS << "\n public:\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000491 OS << " " << R.getName() << "Attr(SourceLocation L, ASTContext &Ctx\n";
Sean Hunt16171442010-06-16 23:45:50 +0000492
Sean Hunt726a3d22010-08-18 23:23:09 +0000493 for (ai = Args.begin(); ai != ae; ++ai) {
494 OS << " , ";
495 (*ai)->writeCtorParameters(OS);
496 OS << "\n";
497 }
Sean Hunt16171442010-06-16 23:45:50 +0000498
Sean Hunt726a3d22010-08-18 23:23:09 +0000499 OS << " )\n";
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000500 OS << " : " << SuperName << "(attr::" << R.getName() << ", L)\n";
Sean Hunt16171442010-06-16 23:45:50 +0000501
Sean Hunt726a3d22010-08-18 23:23:09 +0000502 for (ai = Args.begin(); ai != ae; ++ai) {
503 OS << " , ";
504 (*ai)->writeCtorInitializers(OS);
505 OS << "\n";
506 }
Sean Hunt16171442010-06-16 23:45:50 +0000507
Sean Hunt726a3d22010-08-18 23:23:09 +0000508 OS << " {\n";
509
510 for (ai = Args.begin(); ai != ae; ++ai) {
511 (*ai)->writeCtorBody(OS);
512 OS << "\n";
513 }
514 OS << " }\n\n";
515
516 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
517
518 for (ai = Args.begin(); ai != ae; ++ai) {
519 (*ai)->writeAccessors(OS);
520 OS << "\n\n";
521 }
522
523 OS << R.getValueAsCode("AdditionalMembers");
524 OS << "\n\n";
525
Sean Hunt16171442010-06-16 23:45:50 +0000526 OS << " static bool classof(const Attr *A) { return A->getKind() == "
527 << "attr::" << R.getName() << "; }\n";
528 OS << " static bool classof(const " << R.getName()
529 << "Attr *) { return true; }\n";
530 OS << "};\n\n";
531 }
532
533 OS << "#endif\n";
534}
535
Sean Hunt726a3d22010-08-18 23:23:09 +0000536void ClangAttrImplEmitter::run(raw_ostream &OS) {
537 OS << "// This file is generated by TableGen. Do not edit.\n\n";
538
539 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
540 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
541 std::vector<Argument*>::iterator ai, ae;
542
543 for (; i != e; ++i) {
544 Record &R = **i;
545 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
546 std::vector<Argument*> Args;
547 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
548 Args.push_back(createArgument(**ri, R.getName()));
549
550 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
551 (*ai)->writeAccessorDefinitions(OS);
552
553 OS << R.getName() << "Attr *" << R.getName()
554 << "Attr::clone(ASTContext &C) const {\n";
555 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
556 for (ai = Args.begin(); ai != ae; ++ai) {
557 OS << ", ";
558 (*ai)->writeCloneArgs(OS);
559 }
560 OS << ");\n}\n\n";
561 }
562}
563
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000564static void EmitAttrList(raw_ostream &OS, StringRef Class,
565 const std::vector<Record*> &AttrList) {
566 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
567
568 if (i != e) {
569 // Move the end iterator back to emit the last attribute.
570 for(--e; i != e; ++i)
571 OS << Class << "(" << (*i)->getName() << ")\n";
572
573 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
574 }
575}
576
Sean Hunt16171442010-06-16 23:45:50 +0000577void ClangAttrListEmitter::run(raw_ostream &OS) {
578 OS << "// This file is generated by TableGen. Do not edit.\n\n";
579
580 OS << "#ifndef LAST_ATTR\n";
581 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
582 OS << "#endif\n\n";
Sean Hunt16171442010-06-16 23:45:50 +0000583
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000584 OS << "#ifndef INHERITABLE_ATTR\n";
585 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
586 OS << "#endif\n\n";
587
588 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
589 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
590 OS << "#endif\n\n";
591
592 Record *InhClass = Records.getClass("InheritableAttr");
593 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
594 NonInhAttrs, InhAttrs;
595 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
596 i != e; ++i) {
597 if ((*i)->isSubClassOf(InhClass))
598 InhAttrs.push_back(*i);
599 else
600 NonInhAttrs.push_back(*i);
Sean Hunt16171442010-06-16 23:45:50 +0000601 }
602
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000603 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
604 EmitAttrList(OS, "ATTR", NonInhAttrs);
605
Sean Hunt16171442010-06-16 23:45:50 +0000606 OS << "#undef LAST_ATTR\n";
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000607 OS << "#undef INHERITABLE_ATTR\n";
608 OS << "#undef LAST_INHERITABLE_ATTR\n";
Sean Hunt16171442010-06-16 23:45:50 +0000609 OS << "#undef ATTR\n";
610}
Sean Hunt726a3d22010-08-18 23:23:09 +0000611
612void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
Francois Pichet8ec055d2010-10-01 21:20:39 +0000613 OS << "// This file is generated by TableGen. Do not edit.\n\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000614
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000615 Record *InhClass = Records.getClass("InheritableAttr");
Sean Hunt726a3d22010-08-18 23:23:09 +0000616 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
617 ArgRecords;
618 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
619 std::vector<Argument*> Args;
620 std::vector<Argument*>::iterator ri, re;
621
622 OS << " switch (Kind) {\n";
623 OS << " default:\n";
624 OS << " assert(0 && \"Unknown attribute!\");\n";
625 OS << " break;\n";
626 for (; i != e; ++i) {
627 Record &R = **i;
628 OS << " case attr::" << R.getName() << ": {\n";
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000629 if (R.isSubClassOf(InhClass))
630 OS << " bool isInherited = Record[Idx++];\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000631 ArgRecords = R.getValueAsListOfDefs("Args");
632 Args.clear();
633 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
634 Argument *A = createArgument(**ai, R.getName());
635 Args.push_back(A);
636 A->writePCHReadDecls(OS);
637 }
638 OS << " New = new (*Context) " << R.getName() << "Attr(Loc, *Context";
639 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
640 OS << ", ";
641 (*ri)->writePCHReadArgs(OS);
642 }
643 OS << ");\n";
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000644 if (R.isSubClassOf(InhClass))
645 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000646 OS << " break;\n";
647 OS << " }\n";
648 }
649 OS << " }\n";
650}
651
652void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000653 Record *InhClass = Records.getClass("InheritableAttr");
Sean Hunt726a3d22010-08-18 23:23:09 +0000654 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
655 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
656
657 OS << " switch (A->getKind()) {\n";
658 OS << " default:\n";
659 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
660 OS << " break;\n";
661 for (; i != e; ++i) {
662 Record &R = **i;
663 OS << " case attr::" << R.getName() << ": {\n";
664 Args = R.getValueAsListOfDefs("Args");
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000665 if (R.isSubClassOf(InhClass) || !Args.empty())
Sean Hunt726a3d22010-08-18 23:23:09 +0000666 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
667 << "Attr>(A);\n";
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000668 if (R.isSubClassOf(InhClass))
669 OS << " Record.push_back(SA->isInherited());\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000670 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
671 createArgument(**ai, R.getName())->writePCHWrite(OS);
672 OS << " break;\n";
673 OS << " }\n";
674 }
675 OS << " }\n";
676}
Anders Carlsson238777e2010-10-20 01:21:53 +0000677
678void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
679 OS << "// This file is generated by TableGen. Do not edit.\n\n";
680
681 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
682
683 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
684 Record &Attr = **I;
685
686 std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings");
687
688 for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
689 StringRef Spelling = *I;
690 OS << ".Case(\"" << Spelling << "\", true)\n";
691 }
692 }
693
694}