blob: 2faa49ca45ad1a53fcc3b2e986464fc1090d2785 [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
Sean Hunt726a3d22010-08-18 23:23:09 +000022static const std::vector<StringRef> getValueAsListOfStrings(Record &R,
23 StringRef FieldName) {
24 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 Hunt726a3d22010-08-18 23:23:09 +000048 .Default("Record[Idx++]");
49}
50
51// Assumes that the way to get the value is SA->getname()
52std::string WritePCHRecord(StringRef type, StringRef name) {
53 return StringSwitch<std::string>(type)
54 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
55 ", Record);\n")
56 .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
57 .Default("Record.push_back(" + std::string(name) + ");\n");
58}
59
60namespace {
61 class Argument {
62 std::string lowerName, upperName;
63 StringRef attrName;
64
65 public:
66 Argument(Record &Arg, StringRef Attr)
67 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
68 attrName(Attr) {
69 if (!lowerName.empty()) {
70 lowerName[0] = std::tolower(lowerName[0]);
71 upperName[0] = std::toupper(upperName[0]);
72 }
73 }
Chandler Carruth54f61632010-08-23 08:25:07 +000074 virtual ~Argument() {}
Sean Hunt726a3d22010-08-18 23:23:09 +000075
Sean Hunt5b385002010-08-19 00:03:05 +000076 StringRef getLowerName() const { return lowerName; }
77 StringRef getUpperName() const { return upperName; }
78 StringRef getAttrName() const { return attrName; }
Sean Hunt726a3d22010-08-18 23:23:09 +000079
80 // These functions print the argument contents formatted in different ways.
81 virtual void writeAccessors(raw_ostream &OS) const = 0;
82 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
83 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
84 virtual void writeCtorBody(raw_ostream &OS) const {}
85 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
86 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
87 virtual void writeDeclarations(raw_ostream &OS) const = 0;
88 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
89 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
90 virtual void writePCHWrite(raw_ostream &OS) const = 0;
91 };
92
93 class SimpleArgument : public Argument {
94 std::string type;
95
96 public:
97 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
98 : Argument(Arg, Attr), type(T)
99 {}
100
Sean Hunt726a3d22010-08-18 23:23:09 +0000101 void writeAccessors(raw_ostream &OS) const {
102 OS << " " << type << " get" << getUpperName() << "() const {\n";
103 OS << " return " << getLowerName() << ";\n";
104 OS << " }";
105 }
106 void writeCloneArgs(raw_ostream &OS) const {
107 OS << getLowerName();
108 }
109 void writeCtorInitializers(raw_ostream &OS) const {
110 OS << getLowerName() << "(" << getUpperName() << ")";
111 }
112 void writeCtorParameters(raw_ostream &OS) const {
113 OS << type << " " << getUpperName();
114 }
115 void writeDeclarations(raw_ostream &OS) const {
116 OS << type << " " << getLowerName() << ";";
117 }
118 void writePCHReadDecls(raw_ostream &OS) const {
119 std::string read = ReadPCHRecord(type);
120 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
121 }
122 void writePCHReadArgs(raw_ostream &OS) const {
123 OS << getLowerName();
124 }
125 void writePCHWrite(raw_ostream &OS) const {
126 OS << " " << WritePCHRecord(type, "SA->get" +
127 std::string(getUpperName()) + "()");
128 }
129 };
130
131 class StringArgument : public Argument {
132 public:
133 StringArgument(Record &Arg, StringRef Attr)
134 : Argument(Arg, Attr)
135 {}
136
137 void writeAccessors(raw_ostream &OS) const {
138 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
139 OS << " return llvm::StringRef(" << getLowerName() << ", "
140 << getLowerName() << "Length);\n";
141 OS << " }\n";
142 OS << " unsigned get" << getUpperName() << "Length() const {\n";
143 OS << " return " << getLowerName() << "Length;\n";
144 OS << " }\n";
145 OS << " void set" << getUpperName()
146 << "(ASTContext &C, llvm::StringRef S) {\n";
147 OS << " " << getLowerName() << "Length = S.size();\n";
148 OS << " this->" << getLowerName() << " = new (C, 1) char ["
149 << getLowerName() << "Length];\n";
150 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
151 << getLowerName() << "Length);\n";
152 OS << " }";
153 }
154 void writeCloneArgs(raw_ostream &OS) const {
155 OS << "get" << getUpperName() << "()";
156 }
157 void writeCtorBody(raw_ostream &OS) const {
158 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
159 << ".data(), " << getLowerName() << "Length);";
160 }
161 void writeCtorInitializers(raw_ostream &OS) const {
162 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
163 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
164 << "Length])";
165 }
166 void writeCtorParameters(raw_ostream &OS) const {
167 OS << "llvm::StringRef " << getUpperName();
168 }
169 void writeDeclarations(raw_ostream &OS) const {
170 OS << "unsigned " << getLowerName() << "Length;\n";
171 OS << "char *" << getLowerName() << ";";
172 }
173 void writePCHReadDecls(raw_ostream &OS) const {
174 OS << " std::string " << getLowerName() << "= ReadString(Record, Idx);\n";
175 }
176 void writePCHReadArgs(raw_ostream &OS) const {
177 OS << getLowerName();
178 }
179 void writePCHWrite(raw_ostream &OS) const {
180 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
181 }
182 };
183
184 class AlignedArgument : public Argument {
185 public:
186 AlignedArgument(Record &Arg, StringRef Attr)
187 : Argument(Arg, Attr)
188 {}
189
190 void writeAccessors(raw_ostream &OS) const {
191 OS << " bool is" << getUpperName() << "Dependent() const;\n";
192
193 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
194
195 OS << " bool is" << getUpperName() << "Expr() const {\n";
196 OS << " return is" << getLowerName() << "Expr;\n";
197 OS << " }\n";
198
199 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
200 OS << " assert(is" << getLowerName() << "Expr);\n";
201 OS << " return " << getLowerName() << "Expr;\n";
202 OS << " }\n";
203
204 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
205 OS << " assert(!is" << getLowerName() << "Expr);\n";
206 OS << " return " << getLowerName() << "Type;\n";
207 OS << " }";
208 }
209 void writeAccessorDefinitions(raw_ostream &OS) const {
210 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
211 << "Dependent() const {\n";
212 OS << " if (is" << getLowerName() << "Expr)\n";
213 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
214 << "Expr->isValueDependent() || " << getLowerName()
215 << "Expr->isTypeDependent());\n";
216 OS << " else\n";
217 OS << " return " << getLowerName()
218 << "Type->getType()->isDependentType();\n";
219 OS << "}\n";
220
221 // FIXME: Do not do the calculation here
222 // FIXME: Handle types correctly
223 // A null pointer means maximum alignment
224 // FIXME: Load the platform-specific maximum alignment, rather than
225 // 16, the x86 max.
226 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
227 << "(ASTContext &Ctx) const {\n";
228 OS << " assert(!is" << getUpperName() << "Dependent());\n";
229 OS << " if (is" << getLowerName() << "Expr)\n";
230 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
231 << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)"
232 << "* Ctx.getCharWidth();\n";
233 OS << " else\n";
234 OS << " return 0; // FIXME\n";
235 OS << "}\n";
236 }
237 void writeCloneArgs(raw_ostream &OS) const {
238 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
239 << "Expr ? static_cast<void*>(" << getLowerName()
240 << "Expr) : " << getLowerName()
241 << "Type";
242 }
243 void writeCtorBody(raw_ostream &OS) const {
244 OS << " if (is" << getLowerName() << "Expr)\n";
245 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
246 << getUpperName() << ");\n";
247 OS << " else\n";
248 OS << " " << getLowerName()
249 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
250 << ");";
251 }
252 void writeCtorInitializers(raw_ostream &OS) const {
253 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
254 }
255 void writeCtorParameters(raw_ostream &OS) const {
256 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
257 }
258 void writeDeclarations(raw_ostream &OS) const {
259 OS << "bool is" << getLowerName() << "Expr;\n";
260 OS << "union {\n";
261 OS << "Expr *" << getLowerName() << "Expr;\n";
262 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
263 OS << "};";
264 }
265 void writePCHReadArgs(raw_ostream &OS) const {
266 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
267 }
268 void writePCHReadDecls(raw_ostream &OS) const {
269 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
270 OS << " void *" << getLowerName() << "Ptr;\n";
271 OS << " if (is" << getLowerName() << "Expr)\n";
272 OS << " " << getLowerName() << "Ptr = ReadExpr(DeclsCursor);\n";
273 OS << " else\n";
274 OS << " " << getLowerName()
275 << "Ptr = GetTypeSourceInfo(DeclsCursor, Record, Idx);\n";
276 }
277 void writePCHWrite(raw_ostream &OS) const {
278 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
279 OS << " if (SA->is" << getUpperName() << "Expr())\n";
280 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
281 OS << " else\n";
282 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
283 << "Type(), Record);\n";
284 }
285 };
286
287 class VariadicArgument : public Argument {
288 std::string type;
289
290 public:
291 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
292 : Argument(Arg, Attr), type(T)
293 {}
294
295 std::string getType() const { return type; }
296
297 void writeAccessors(raw_ostream &OS) const {
298 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
299 OS << " " << getLowerName() << "_iterator " << getLowerName()
300 << "_begin() const {\n";
301 OS << " return " << getLowerName() << ";\n";
302 OS << " }\n";
303 OS << " " << getLowerName() << "_iterator " << getLowerName()
304 << "_end() const {\n";
305 OS << " return " << getLowerName() << " + " << getLowerName()
306 << "Size;\n";
307 OS << " }\n";
308 OS << " unsigned " << getLowerName() << "_size() const {\n"
309 << " return " << getLowerName() << "Size;\n;";
310 OS << " }";
311 }
312 void writeCloneArgs(raw_ostream &OS) const {
313 OS << getLowerName() << ", " << getLowerName() << "Size";
314 }
315 void writeCtorBody(raw_ostream &OS) const {
316 // FIXME: memcpy is not safe on non-trivial types.
317 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
318 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
319 }
320 void writeCtorInitializers(raw_ostream &OS) const {
321 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
322 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
323 << getLowerName() << "Size])";
324 }
325 void writeCtorParameters(raw_ostream &OS) const {
326 OS << getType() << " *" << getUpperName() << ", unsigned "
327 << getUpperName() << "Size";
328 }
329 void writeDeclarations(raw_ostream &OS) const {
330 OS << " unsigned " << getLowerName() << "Size;\n";
331 OS << " " << getType() << " *" << getLowerName() << ";";
332 }
333 void writePCHReadDecls(raw_ostream &OS) const {
334 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
335 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
336 << ";\n";
337 OS << " " << getLowerName() << ".reserve(" << getLowerName()
338 << "Size);\n";
339 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
340
341 std::string read = ReadPCHRecord(type);
342 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
343 }
344 void writePCHReadArgs(raw_ostream &OS) const {
345 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
346 }
347 void writePCHWrite(raw_ostream &OS) const{
348 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
349 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
350 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
351 << getLowerName() << "_end(); i != e; ++i)\n";
352 OS << " " << WritePCHRecord(type, "(*i)");
353 }
354 };
355
356 class EnumArgument : public Argument {
Eli Friedmana8fa3922010-08-19 06:11:05 +0000357 std::string type;
Sean Hunt726a3d22010-08-18 23:23:09 +0000358 std::vector<StringRef> values, enums;
359 public:
360 EnumArgument(Record &Arg, StringRef Attr)
361 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
362 values(getValueAsListOfStrings(Arg, "Values")),
363 enums(getValueAsListOfStrings(Arg, "Enums"))
364 {}
365
366 void writeAccessors(raw_ostream &OS) const {
367 OS << " " << type << " get" << getUpperName() << "() const {\n";
368 OS << " return " << getLowerName() << ";\n";
369 OS << " }";
370 }
371 void writeCloneArgs(raw_ostream &OS) const {
372 OS << getLowerName();
373 }
374 void writeCtorInitializers(raw_ostream &OS) const {
375 OS << getLowerName() << "(" << getUpperName() << ")";
376 }
377 void writeCtorParameters(raw_ostream &OS) const {
378 OS << type << " " << getUpperName();
379 }
380 void writeDeclarations(raw_ostream &OS) const {
381 // Calculate the various enum values
382 std::vector<StringRef> uniques(enums);
383 std::sort(uniques.begin(), uniques.end());
384 uniques.erase(std::unique(uniques.begin(), uniques.end()),
385 uniques.end());
386 // FIXME: Emit a proper error
387 assert(!uniques.empty());
388
389 std::vector<StringRef>::iterator i = uniques.begin(),
390 e = uniques.end();
391 // The last one needs to not have a comma.
392 --e;
393
394 OS << "public:\n";
395 OS << " enum " << type << " {\n";
396 for (; i != e; ++i)
397 OS << " " << *i << ",\n";
398 OS << " " << *e << "\n";
399 OS << " };\n";
400 OS << "private:\n";
401 OS << " " << type << " " << getLowerName() << ";";
402 }
403 void writePCHReadDecls(raw_ostream &OS) const {
404 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
405 << "(static_cast<" << getAttrName() << "Attr::" << type
406 << ">(Record[Idx++]));\n";
407 }
408 void writePCHReadArgs(raw_ostream &OS) const {
409 OS << getLowerName();
410 }
411 void writePCHWrite(raw_ostream &OS) const {
412 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
413 }
414 };
415}
416
417static Argument *createArgument(Record &Arg, StringRef Attr,
418 Record *Search = 0) {
419 if (!Search)
420 Search = &Arg;
421
422 Argument *Ptr = 0;
423 llvm::StringRef ArgName = Search->getName();
424
425 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
426 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
427 else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
428 "Expr *");
429 else if (ArgName == "FunctionArgument")
430 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
431 else if (ArgName == "IdentifierArgument")
432 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
433 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
434 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
435 else if (ArgName == "TypeArgument")
436 Ptr = new SimpleArgument(Arg, Attr, "QualType");
437 else if (ArgName == "UnsignedArgument")
438 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
439 else if (ArgName == "VariadicUnsignedArgument")
440 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
441
442 if (!Ptr) {
443 std::vector<Record*> Bases = Search->getSuperClasses();
444 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
445 i != e; ++i) {
446 Ptr = createArgument(Arg, Attr, *i);
447 if (Ptr)
448 break;
449 }
450 }
451 return Ptr;
452}
453
Sean Hunt16171442010-06-16 23:45:50 +0000454void ClangAttrClassEmitter::run(raw_ostream &OS) {
455 OS << "// This file is generated by TableGen. Do not edit.\n\n";
456 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
457 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
458
459 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
460
461 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
462 i != e; ++i) {
463 Record &R = **i;
464
Sean Hunt16171442010-06-16 23:45:50 +0000465 OS << "class " << R.getName() << "Attr : public Attr {\n";
466
Sean Hunt726a3d22010-08-18 23:23:09 +0000467 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
468 std::vector<Argument*> Args;
469 std::vector<Argument*>::iterator ai, ae;
470 Args.reserve(ArgRecords.size());
Sean Hunt16171442010-06-16 23:45:50 +0000471
Sean Hunt726a3d22010-08-18 23:23:09 +0000472 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
473 re = ArgRecords.end();
474 ri != re; ++ri) {
475 Record &ArgRecord = **ri;
476 Argument *Arg = createArgument(ArgRecord, R.getName());
477 assert(Arg);
478 Args.push_back(Arg);
479
480 Arg->writeDeclarations(OS);
481 OS << "\n\n";
482 }
483
484 ae = Args.end();
Sean Hunt16171442010-06-16 23:45:50 +0000485
486 OS << "\n public:\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000487 OS << " " << R.getName() << "Attr(SourceLocation L, ASTContext &Ctx\n";
Sean Hunt16171442010-06-16 23:45:50 +0000488
Sean Hunt726a3d22010-08-18 23:23:09 +0000489 for (ai = Args.begin(); ai != ae; ++ai) {
490 OS << " , ";
491 (*ai)->writeCtorParameters(OS);
492 OS << "\n";
493 }
Sean Hunt16171442010-06-16 23:45:50 +0000494
Sean Hunt726a3d22010-08-18 23:23:09 +0000495 OS << " )\n";
496 OS << " : Attr(attr::" << R.getName() << ", L)\n";
Sean Hunt16171442010-06-16 23:45:50 +0000497
Sean Hunt726a3d22010-08-18 23:23:09 +0000498 for (ai = Args.begin(); ai != ae; ++ai) {
499 OS << " , ";
500 (*ai)->writeCtorInitializers(OS);
501 OS << "\n";
502 }
Sean Hunt16171442010-06-16 23:45:50 +0000503
Sean Hunt726a3d22010-08-18 23:23:09 +0000504 OS << " {\n";
505
506 for (ai = Args.begin(); ai != ae; ++ai) {
507 (*ai)->writeCtorBody(OS);
508 OS << "\n";
509 }
510 OS << " }\n\n";
511
512 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
513
514 for (ai = Args.begin(); ai != ae; ++ai) {
515 (*ai)->writeAccessors(OS);
516 OS << "\n\n";
517 }
518
519 OS << R.getValueAsCode("AdditionalMembers");
520 OS << "\n\n";
521
Sean Hunt16171442010-06-16 23:45:50 +0000522 OS << " static bool classof(const Attr *A) { return A->getKind() == "
523 << "attr::" << R.getName() << "; }\n";
524 OS << " static bool classof(const " << R.getName()
525 << "Attr *) { return true; }\n";
526 OS << "};\n\n";
527 }
528
529 OS << "#endif\n";
530}
531
Sean Hunt726a3d22010-08-18 23:23:09 +0000532void ClangAttrImplEmitter::run(raw_ostream &OS) {
533 OS << "// This file is generated by TableGen. Do not edit.\n\n";
534
535 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
536 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
537 std::vector<Argument*>::iterator ai, ae;
538
539 for (; i != e; ++i) {
540 Record &R = **i;
541 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
542 std::vector<Argument*> Args;
543 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
544 Args.push_back(createArgument(**ri, R.getName()));
545
546 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
547 (*ai)->writeAccessorDefinitions(OS);
548
549 OS << R.getName() << "Attr *" << R.getName()
550 << "Attr::clone(ASTContext &C) const {\n";
551 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
552 for (ai = Args.begin(); ai != ae; ++ai) {
553 OS << ", ";
554 (*ai)->writeCloneArgs(OS);
555 }
556 OS << ");\n}\n\n";
557 }
558}
559
Sean Hunt16171442010-06-16 23:45:50 +0000560void ClangAttrListEmitter::run(raw_ostream &OS) {
561 OS << "// This file is generated by TableGen. Do not edit.\n\n";
562
563 OS << "#ifndef LAST_ATTR\n";
564 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
565 OS << "#endif\n\n";
566
567 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
568 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
569
570 if (i != e) {
571 // Move the end iterator back to emit the last attribute.
572 for(--e; i != e; ++i)
573 OS << "ATTR(" << (*i)->getName() << ")\n";
574
575 OS << "LAST_ATTR(" << (*i)->getName() << ")\n\n";
576 }
577
578 OS << "#undef LAST_ATTR\n";
579 OS << "#undef ATTR\n";
580}
Sean Hunt726a3d22010-08-18 23:23:09 +0000581
582void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
Francois Pichet8ec055d2010-10-01 21:20:39 +0000583 OS << "// This file is generated by TableGen. Do not edit.\n\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000584
585 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
586 ArgRecords;
587 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
588 std::vector<Argument*> Args;
589 std::vector<Argument*>::iterator ri, re;
590
591 OS << " switch (Kind) {\n";
592 OS << " default:\n";
593 OS << " assert(0 && \"Unknown attribute!\");\n";
594 OS << " break;\n";
595 for (; i != e; ++i) {
596 Record &R = **i;
597 OS << " case attr::" << R.getName() << ": {\n";
598 ArgRecords = R.getValueAsListOfDefs("Args");
599 Args.clear();
600 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
601 Argument *A = createArgument(**ai, R.getName());
602 Args.push_back(A);
603 A->writePCHReadDecls(OS);
604 }
605 OS << " New = new (*Context) " << R.getName() << "Attr(Loc, *Context";
606 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
607 OS << ", ";
608 (*ri)->writePCHReadArgs(OS);
609 }
610 OS << ");\n";
611 OS << " break;\n";
612 OS << " }\n";
613 }
614 OS << " }\n";
615}
616
617void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
618 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
619 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
620
621 OS << " switch (A->getKind()) {\n";
622 OS << " default:\n";
623 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
624 OS << " break;\n";
625 for (; i != e; ++i) {
626 Record &R = **i;
627 OS << " case attr::" << R.getName() << ": {\n";
628 Args = R.getValueAsListOfDefs("Args");
629 if (!Args.empty())
630 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
631 << "Attr>(A);\n";
632 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
633 createArgument(**ai, R.getName())->writePCHWrite(OS);
634 OS << " break;\n";
635 OS << " }\n";
636 }
637 OS << " }\n";
638}