blob: 7db1ababb10ab38d22f94c3dbbcee26477d45f00 [file] [log] [blame]
Peter Collingbourne51d77772011-10-06 13:03:08 +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 "llvm/ADT/StringSwitch.h"
16#include "llvm/TableGen/Record.h"
17#include <algorithm>
18#include <cctype>
19
20using namespace llvm;
21
22static const std::vector<StringRef>
23getValueAsListOfStrings(Record &R, 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::const_iterator i = List->begin(), e = List->end();
31 i != e;
32 ++i) {
33 assert(*i && "Got a null element in a ListInit");
34 if (StringInit *S = dynamic_cast<StringInit *>(*i))
35 Strings.push_back(S->getValue());
Peter Collingbourne51d77772011-10-06 13:03:08 +000036 else
37 assert(false && "Got a non-string, non-code element in a ListInit");
38 }
39
40 return Strings;
41}
42
43static std::string ReadPCHRecord(StringRef type) {
44 return StringSwitch<std::string>(type)
45 .EndsWith("Decl *", "GetLocalDeclAs<"
46 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
47 .Case("QualType", "getLocalType(F, Record[Idx++])")
48 .Case("Expr *", "ReadSubExpr()")
49 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
50 .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)")
51 .Default("Record[Idx++]");
52}
53
54// Assumes that the way to get the value is SA->getname()
55static std::string WritePCHRecord(StringRef type, StringRef name) {
56 return StringSwitch<std::string>(type)
57 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
58 ", Record);\n")
59 .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
60 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
61 .Case("IdentifierInfo *",
62 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
63 .Case("SourceLocation",
64 "AddSourceLocation(" + std::string(name) + ", Record);\n")
65 .Default("Record.push_back(" + std::string(name) + ");\n");
66}
67
68namespace {
69 class Argument {
70 std::string lowerName, upperName;
71 StringRef attrName;
72
73 public:
74 Argument(Record &Arg, StringRef Attr)
75 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
76 attrName(Attr) {
77 if (!lowerName.empty()) {
78 lowerName[0] = std::tolower(lowerName[0]);
79 upperName[0] = std::toupper(upperName[0]);
80 }
81 }
82 virtual ~Argument() {}
83
84 StringRef getLowerName() const { return lowerName; }
85 StringRef getUpperName() const { return upperName; }
86 StringRef getAttrName() const { return attrName; }
87
88 // These functions print the argument contents formatted in different ways.
89 virtual void writeAccessors(raw_ostream &OS) const = 0;
90 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
91 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +000092 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
93 virtual void writeTemplateInstantiation(raw_ostream &OS) const {};
Peter Collingbourne51d77772011-10-06 13:03:08 +000094 virtual void writeCtorBody(raw_ostream &OS) const {}
95 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
96 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
97 virtual void writeDeclarations(raw_ostream &OS) const = 0;
98 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
99 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
100 virtual void writePCHWrite(raw_ostream &OS) const = 0;
Douglas Gregor1bea8802011-11-19 19:22:57 +0000101 virtual void writeValue(raw_ostream &OS) const = 0;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000102 };
103
104 class SimpleArgument : public Argument {
105 std::string type;
106
107 public:
108 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
109 : Argument(Arg, Attr), type(T)
110 {}
111
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000112 std::string getType() const { return type; }
113
Peter Collingbourne51d77772011-10-06 13:03:08 +0000114 void writeAccessors(raw_ostream &OS) const {
115 OS << " " << type << " get" << getUpperName() << "() const {\n";
116 OS << " return " << getLowerName() << ";\n";
117 OS << " }";
118 }
119 void writeCloneArgs(raw_ostream &OS) const {
120 OS << getLowerName();
121 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000122 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
123 OS << "A->get" << getUpperName() << "()";
124 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000125 void writeCtorInitializers(raw_ostream &OS) const {
126 OS << getLowerName() << "(" << getUpperName() << ")";
127 }
128 void writeCtorParameters(raw_ostream &OS) const {
129 OS << type << " " << getUpperName();
130 }
131 void writeDeclarations(raw_ostream &OS) const {
132 OS << type << " " << getLowerName() << ";";
133 }
134 void writePCHReadDecls(raw_ostream &OS) const {
135 std::string read = ReadPCHRecord(type);
136 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
137 }
138 void writePCHReadArgs(raw_ostream &OS) const {
139 OS << getLowerName();
140 }
141 void writePCHWrite(raw_ostream &OS) const {
142 OS << " " << WritePCHRecord(type, "SA->get" +
143 std::string(getUpperName()) + "()");
144 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000145 void writeValue(raw_ostream &OS) const {
146 if (type == "FunctionDecl *") {
147 OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \"";
148 } else if (type == "IdentifierInfo *") {
149 OS << "\" << get" << getUpperName() << "()->getName() << \"";
150 } else if (type == "QualType") {
151 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
152 } else if (type == "SourceLocation") {
153 OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
154 } else {
155 OS << "\" << get" << getUpperName() << "() << \"";
156 }
157 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000158 };
159
160 class StringArgument : public Argument {
161 public:
162 StringArgument(Record &Arg, StringRef Attr)
163 : Argument(Arg, Attr)
164 {}
165
166 void writeAccessors(raw_ostream &OS) const {
167 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
168 OS << " return llvm::StringRef(" << getLowerName() << ", "
169 << getLowerName() << "Length);\n";
170 OS << " }\n";
171 OS << " unsigned get" << getUpperName() << "Length() const {\n";
172 OS << " return " << getLowerName() << "Length;\n";
173 OS << " }\n";
174 OS << " void set" << getUpperName()
175 << "(ASTContext &C, llvm::StringRef S) {\n";
176 OS << " " << getLowerName() << "Length = S.size();\n";
177 OS << " this->" << getLowerName() << " = new (C, 1) char ["
178 << getLowerName() << "Length];\n";
179 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
180 << getLowerName() << "Length);\n";
181 OS << " }";
182 }
183 void writeCloneArgs(raw_ostream &OS) const {
184 OS << "get" << getUpperName() << "()";
185 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000186 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
187 OS << "A->get" << getUpperName() << "()";
188 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000189 void writeCtorBody(raw_ostream &OS) const {
190 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
191 << ".data(), " << getLowerName() << "Length);";
192 }
193 void writeCtorInitializers(raw_ostream &OS) const {
194 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
195 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
196 << "Length])";
197 }
198 void writeCtorParameters(raw_ostream &OS) const {
199 OS << "llvm::StringRef " << getUpperName();
200 }
201 void writeDeclarations(raw_ostream &OS) const {
202 OS << "unsigned " << getLowerName() << "Length;\n";
203 OS << "char *" << getLowerName() << ";";
204 }
205 void writePCHReadDecls(raw_ostream &OS) const {
206 OS << " std::string " << getLowerName()
207 << "= ReadString(Record, Idx);\n";
208 }
209 void writePCHReadArgs(raw_ostream &OS) const {
210 OS << getLowerName();
211 }
212 void writePCHWrite(raw_ostream &OS) const {
213 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
214 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000215 void writeValue(raw_ostream &OS) const {
216 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
217 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000218 };
219
220 class AlignedArgument : public Argument {
221 public:
222 AlignedArgument(Record &Arg, StringRef Attr)
223 : Argument(Arg, Attr)
224 {}
225
226 void writeAccessors(raw_ostream &OS) const {
227 OS << " bool is" << getUpperName() << "Dependent() const;\n";
228
229 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
230
231 OS << " bool is" << getUpperName() << "Expr() const {\n";
232 OS << " return is" << getLowerName() << "Expr;\n";
233 OS << " }\n";
234
235 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
236 OS << " assert(is" << getLowerName() << "Expr);\n";
237 OS << " return " << getLowerName() << "Expr;\n";
238 OS << " }\n";
239
240 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
241 OS << " assert(!is" << getLowerName() << "Expr);\n";
242 OS << " return " << getLowerName() << "Type;\n";
243 OS << " }";
244 }
245 void writeAccessorDefinitions(raw_ostream &OS) const {
246 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
247 << "Dependent() const {\n";
248 OS << " if (is" << getLowerName() << "Expr)\n";
249 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
250 << "Expr->isValueDependent() || " << getLowerName()
251 << "Expr->isTypeDependent());\n";
252 OS << " else\n";
253 OS << " return " << getLowerName()
254 << "Type->getType()->isDependentType();\n";
255 OS << "}\n";
256
257 // FIXME: Do not do the calculation here
258 // FIXME: Handle types correctly
259 // A null pointer means maximum alignment
260 // FIXME: Load the platform-specific maximum alignment, rather than
261 // 16, the x86 max.
262 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
263 << "(ASTContext &Ctx) const {\n";
264 OS << " assert(!is" << getUpperName() << "Dependent());\n";
265 OS << " if (is" << getLowerName() << "Expr)\n";
266 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smitha6b8b2c2011-10-10 18:28:20 +0000267 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbourne51d77772011-10-06 13:03:08 +0000268 << "* Ctx.getCharWidth();\n";
269 OS << " else\n";
270 OS << " return 0; // FIXME\n";
271 OS << "}\n";
272 }
273 void writeCloneArgs(raw_ostream &OS) const {
274 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
275 << "Expr ? static_cast<void*>(" << getLowerName()
276 << "Expr) : " << getLowerName()
277 << "Type";
278 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000279 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
280 // FIXME: move the definition in Sema::InstantiateAttrs to here.
281 // In the meantime, aligned attributes are cloned.
282 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000283 void writeCtorBody(raw_ostream &OS) const {
284 OS << " if (is" << getLowerName() << "Expr)\n";
285 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
286 << getUpperName() << ");\n";
287 OS << " else\n";
288 OS << " " << getLowerName()
289 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
290 << ");";
291 }
292 void writeCtorInitializers(raw_ostream &OS) const {
293 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
294 }
295 void writeCtorParameters(raw_ostream &OS) const {
296 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
297 }
298 void writeDeclarations(raw_ostream &OS) const {
299 OS << "bool is" << getLowerName() << "Expr;\n";
300 OS << "union {\n";
301 OS << "Expr *" << getLowerName() << "Expr;\n";
302 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
303 OS << "};";
304 }
305 void writePCHReadArgs(raw_ostream &OS) const {
306 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
307 }
308 void writePCHReadDecls(raw_ostream &OS) const {
309 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
310 OS << " void *" << getLowerName() << "Ptr;\n";
311 OS << " if (is" << getLowerName() << "Expr)\n";
312 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
313 OS << " else\n";
314 OS << " " << getLowerName()
315 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
316 }
317 void writePCHWrite(raw_ostream &OS) const {
318 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
319 OS << " if (SA->is" << getUpperName() << "Expr())\n";
320 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
321 OS << " else\n";
322 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
323 << "Type(), Record);\n";
324 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000325 void writeValue(raw_ostream &OS) const {
326 OS << "\" << get" << getUpperName() << "(Ctx) << \"";
327 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000328 };
329
330 class VariadicArgument : public Argument {
331 std::string type;
332
333 public:
334 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
335 : Argument(Arg, Attr), type(T)
336 {}
337
338 std::string getType() const { return type; }
339
340 void writeAccessors(raw_ostream &OS) const {
341 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
342 OS << " " << getLowerName() << "_iterator " << getLowerName()
343 << "_begin() const {\n";
344 OS << " return " << getLowerName() << ";\n";
345 OS << " }\n";
346 OS << " " << getLowerName() << "_iterator " << getLowerName()
347 << "_end() const {\n";
348 OS << " return " << getLowerName() << " + " << getLowerName()
349 << "Size;\n";
350 OS << " }\n";
351 OS << " unsigned " << getLowerName() << "_size() const {\n"
DeLesley Hutchins23323e02012-01-20 22:50:54 +0000352 << " return " << getLowerName() << "Size;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000353 OS << " }";
354 }
355 void writeCloneArgs(raw_ostream &OS) const {
356 OS << getLowerName() << ", " << getLowerName() << "Size";
357 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000358 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
359 // This isn't elegant, but we have to go through public methods...
360 OS << "A->" << getLowerName() << "_begin(), "
361 << "A->" << getLowerName() << "_size()";
362 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000363 void writeCtorBody(raw_ostream &OS) const {
364 // FIXME: memcpy is not safe on non-trivial types.
365 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
366 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
367 }
368 void writeCtorInitializers(raw_ostream &OS) const {
369 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
370 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
371 << getLowerName() << "Size])";
372 }
373 void writeCtorParameters(raw_ostream &OS) const {
374 OS << getType() << " *" << getUpperName() << ", unsigned "
375 << getUpperName() << "Size";
376 }
377 void writeDeclarations(raw_ostream &OS) const {
378 OS << " unsigned " << getLowerName() << "Size;\n";
379 OS << " " << getType() << " *" << getLowerName() << ";";
380 }
381 void writePCHReadDecls(raw_ostream &OS) const {
382 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
383 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
384 << ";\n";
385 OS << " " << getLowerName() << ".reserve(" << getLowerName()
386 << "Size);\n";
387 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
388
389 std::string read = ReadPCHRecord(type);
390 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
391 }
392 void writePCHReadArgs(raw_ostream &OS) const {
393 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
394 }
395 void writePCHWrite(raw_ostream &OS) const{
396 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
397 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
398 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
399 << getLowerName() << "_end(); i != e; ++i)\n";
400 OS << " " << WritePCHRecord(type, "(*i)");
401 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000402 void writeValue(raw_ostream &OS) const {
403 OS << "\";\n";
404 OS << " bool isFirst = true;\n"
405 << " for (" << getAttrName() << "Attr::" << getLowerName()
406 << "_iterator i = " << getLowerName() << "_begin(), e = "
407 << getLowerName() << "_end(); i != e; ++i) {\n"
408 << " if (isFirst) isFirst = false;\n"
409 << " else OS << \", \";\n"
410 << " OS << *i;\n"
411 << " }\n";
412 OS << " OS << \"";
413 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000414 };
415
416 class EnumArgument : public Argument {
417 std::string type;
418 std::vector<StringRef> values, enums;
419 public:
420 EnumArgument(Record &Arg, StringRef Attr)
421 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
422 values(getValueAsListOfStrings(Arg, "Values")),
423 enums(getValueAsListOfStrings(Arg, "Enums"))
424 {}
425
426 void writeAccessors(raw_ostream &OS) const {
427 OS << " " << type << " get" << getUpperName() << "() const {\n";
428 OS << " return " << getLowerName() << ";\n";
429 OS << " }";
430 }
431 void writeCloneArgs(raw_ostream &OS) const {
432 OS << getLowerName();
433 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000434 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
435 OS << "A->get" << getUpperName() << "()";
436 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000437 void writeCtorInitializers(raw_ostream &OS) const {
438 OS << getLowerName() << "(" << getUpperName() << ")";
439 }
440 void writeCtorParameters(raw_ostream &OS) const {
441 OS << type << " " << getUpperName();
442 }
443 void writeDeclarations(raw_ostream &OS) const {
444 // Calculate the various enum values
445 std::vector<StringRef> uniques(enums);
446 std::sort(uniques.begin(), uniques.end());
447 uniques.erase(std::unique(uniques.begin(), uniques.end()),
448 uniques.end());
449 // FIXME: Emit a proper error
450 assert(!uniques.empty());
451
452 std::vector<StringRef>::iterator i = uniques.begin(),
453 e = uniques.end();
454 // The last one needs to not have a comma.
455 --e;
456
457 OS << "public:\n";
458 OS << " enum " << type << " {\n";
459 for (; i != e; ++i)
460 OS << " " << *i << ",\n";
461 OS << " " << *e << "\n";
462 OS << " };\n";
463 OS << "private:\n";
464 OS << " " << type << " " << getLowerName() << ";";
465 }
466 void writePCHReadDecls(raw_ostream &OS) const {
467 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
468 << "(static_cast<" << getAttrName() << "Attr::" << type
469 << ">(Record[Idx++]));\n";
470 }
471 void writePCHReadArgs(raw_ostream &OS) const {
472 OS << getLowerName();
473 }
474 void writePCHWrite(raw_ostream &OS) const {
475 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
476 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000477 void writeValue(raw_ostream &OS) const {
478 OS << "\" << get" << getUpperName() << "() << \"";
479 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000480 };
481
482 class VersionArgument : public Argument {
483 public:
484 VersionArgument(Record &Arg, StringRef Attr)
485 : Argument(Arg, Attr)
486 {}
487
488 void writeAccessors(raw_ostream &OS) const {
489 OS << " VersionTuple get" << getUpperName() << "() const {\n";
490 OS << " return " << getLowerName() << ";\n";
491 OS << " }\n";
492 OS << " void set" << getUpperName()
493 << "(ASTContext &C, VersionTuple V) {\n";
494 OS << " " << getLowerName() << " = V;\n";
495 OS << " }";
496 }
497 void writeCloneArgs(raw_ostream &OS) const {
498 OS << "get" << getUpperName() << "()";
499 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000500 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
501 OS << "A->get" << getUpperName() << "()";
502 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000503 void writeCtorBody(raw_ostream &OS) const {
504 }
505 void writeCtorInitializers(raw_ostream &OS) const {
506 OS << getLowerName() << "(" << getUpperName() << ")";
507 }
508 void writeCtorParameters(raw_ostream &OS) const {
509 OS << "VersionTuple " << getUpperName();
510 }
511 void writeDeclarations(raw_ostream &OS) const {
512 OS << "VersionTuple " << getLowerName() << ";\n";
513 }
514 void writePCHReadDecls(raw_ostream &OS) const {
515 OS << " VersionTuple " << getLowerName()
516 << "= ReadVersionTuple(Record, Idx);\n";
517 }
518 void writePCHReadArgs(raw_ostream &OS) const {
519 OS << getLowerName();
520 }
521 void writePCHWrite(raw_ostream &OS) const {
522 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
523 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000524 void writeValue(raw_ostream &OS) const {
525 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
526 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000527 };
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000528
529 class ExprArgument : public SimpleArgument {
530 public:
531 ExprArgument(Record &Arg, StringRef Attr)
532 : SimpleArgument(Arg, Attr, "Expr *")
533 {}
534
535 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
536 OS << "tempInst" << getUpperName();
537 }
538
539 void writeTemplateInstantiation(raw_ostream &OS) const {
540 OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
541 OS << " {\n";
542 OS << " EnterExpressionEvaluationContext "
543 << "Unevaluated(S, Sema::Unevaluated);\n";
544 OS << " ExprResult " << "Result = S.SubstExpr("
545 << "A->get" << getUpperName() << "(), TemplateArgs);\n";
546 OS << " tempInst" << getUpperName() << " = "
547 << "Result.takeAs<Expr>();\n";
548 OS << " }\n";
549 }
550 };
551
552 class VariadicExprArgument : public VariadicArgument {
553 public:
554 VariadicExprArgument(Record &Arg, StringRef Attr)
555 : VariadicArgument(Arg, Attr, "Expr *")
556 {}
557
558 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
559 OS << "tempInst" << getUpperName() << ", "
560 << "A->" << getLowerName() << "_size()";
561 }
562
563 void writeTemplateInstantiation(raw_ostream &OS) const {
564 OS << " " << getType() << " *tempInst" << getUpperName()
565 << " = new (C, 16) " << getType()
566 << "[A->" << getLowerName() << "_size()];\n";
567 OS << " {\n";
568 OS << " EnterExpressionEvaluationContext "
569 << "Unevaluated(S, Sema::Unevaluated);\n";
570 OS << " " << getType() << " *TI = tempInst" << getUpperName()
571 << ";\n";
572 OS << " " << getType() << " *I = A->" << getLowerName()
573 << "_begin();\n";
574 OS << " " << getType() << " *E = A->" << getLowerName()
575 << "_end();\n";
576 OS << " for (; I != E; ++I, ++TI) {\n";
577 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
578 OS << " *TI = Result.takeAs<Expr>();\n";
579 OS << " }\n";
580 OS << " }\n";
581 }
582 };
Peter Collingbourne51d77772011-10-06 13:03:08 +0000583}
584
585static Argument *createArgument(Record &Arg, StringRef Attr,
586 Record *Search = 0) {
587 if (!Search)
588 Search = &Arg;
589
590 Argument *Ptr = 0;
591 llvm::StringRef ArgName = Search->getName();
592
593 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
594 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000595 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000596 else if (ArgName == "FunctionArgument")
597 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
598 else if (ArgName == "IdentifierArgument")
599 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
600 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
601 "bool");
602 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
603 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
604 else if (ArgName == "TypeArgument")
605 Ptr = new SimpleArgument(Arg, Attr, "QualType");
606 else if (ArgName == "UnsignedArgument")
607 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
608 else if (ArgName == "SourceLocArgument")
609 Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
610 else if (ArgName == "VariadicUnsignedArgument")
611 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
612 else if (ArgName == "VariadicExprArgument")
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000613 Ptr = new VariadicExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000614 else if (ArgName == "VersionArgument")
615 Ptr = new VersionArgument(Arg, Attr);
616
617 if (!Ptr) {
618 std::vector<Record*> Bases = Search->getSuperClasses();
619 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
620 i != e; ++i) {
621 Ptr = createArgument(Arg, Attr, *i);
622 if (Ptr)
623 break;
624 }
625 }
626 return Ptr;
627}
628
Douglas Gregor1bea8802011-11-19 19:22:57 +0000629static void writeAvailabilityValue(raw_ostream &OS) {
630 OS << "\" << getPlatform()->getName();\n"
631 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
632 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
633 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
634 << " if (getUnavailable()) OS << \", unavailable\";\n"
635 << " OS << \"";
636}
637
Peter Collingbourne51d77772011-10-06 13:03:08 +0000638void ClangAttrClassEmitter::run(raw_ostream &OS) {
639 OS << "// This file is generated by TableGen. Do not edit.\n\n";
640 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
641 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
642
643 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
644
645 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
646 i != e; ++i) {
647 Record &R = **i;
648 const std::string &SuperName = R.getSuperClasses().back()->getName();
649
650 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
651
652 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
653 std::vector<Argument*> Args;
654 std::vector<Argument*>::iterator ai, ae;
655 Args.reserve(ArgRecords.size());
656
657 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
658 re = ArgRecords.end();
659 ri != re; ++ri) {
660 Record &ArgRecord = **ri;
661 Argument *Arg = createArgument(ArgRecord, R.getName());
662 assert(Arg);
663 Args.push_back(Arg);
664
665 Arg->writeDeclarations(OS);
666 OS << "\n\n";
667 }
668
669 ae = Args.end();
670
671 OS << "\n public:\n";
672 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
673
674 for (ai = Args.begin(); ai != ae; ++ai) {
675 OS << " , ";
676 (*ai)->writeCtorParameters(OS);
677 OS << "\n";
678 }
679
680 OS << " )\n";
681 OS << " : " << SuperName << "(attr::" << R.getName() << ", R)\n";
682
683 for (ai = Args.begin(); ai != ae; ++ai) {
684 OS << " , ";
685 (*ai)->writeCtorInitializers(OS);
686 OS << "\n";
687 }
688
689 OS << " {\n";
690
691 for (ai = Args.begin(); ai != ae; ++ai) {
692 (*ai)->writeCtorBody(OS);
693 OS << "\n";
694 }
695 OS << " }\n\n";
696
697 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000698 OS << " virtual void printPretty(llvm::raw_ostream &OS, ASTContext &Ctx) const;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000699
700 for (ai = Args.begin(); ai != ae; ++ai) {
701 (*ai)->writeAccessors(OS);
702 OS << "\n\n";
703 }
704
Jakob Stoklund Oleseneb666732012-01-13 04:57:47 +0000705 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000706 OS << "\n\n";
707
708 OS << " static bool classof(const Attr *A) { return A->getKind() == "
709 << "attr::" << R.getName() << "; }\n";
710 OS << " static bool classof(const " << R.getName()
711 << "Attr *) { return true; }\n";
DeLesley Hutchins23323e02012-01-20 22:50:54 +0000712
713 bool LateParsed = R.getValueAsBit("LateParsed");
714 OS << " virtual bool isLateParsed() const { return "
715 << LateParsed << "; }\n";
716
Peter Collingbourne51d77772011-10-06 13:03:08 +0000717 OS << "};\n\n";
718 }
719
720 OS << "#endif\n";
721}
722
723void ClangAttrImplEmitter::run(raw_ostream &OS) {
724 OS << "// This file is generated by TableGen. Do not edit.\n\n";
725
726 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
727 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
728 std::vector<Argument*>::iterator ai, ae;
729
730 for (; i != e; ++i) {
731 Record &R = **i;
732 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Douglas Gregor1bea8802011-11-19 19:22:57 +0000733 std::vector<StringRef> Spellings = getValueAsListOfStrings(R, "Spellings");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000734 std::vector<Argument*> Args;
735 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
736 Args.push_back(createArgument(**ri, R.getName()));
737
738 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
739 (*ai)->writeAccessorDefinitions(OS);
740
741 OS << R.getName() << "Attr *" << R.getName()
742 << "Attr::clone(ASTContext &C) const {\n";
743 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
744 for (ai = Args.begin(); ai != ae; ++ai) {
745 OS << ", ";
746 (*ai)->writeCloneArgs(OS);
747 }
748 OS << ");\n}\n\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000749
750 OS << "void " << R.getName() << "Attr::printPretty("
751 << "llvm::raw_ostream &OS, ASTContext &Ctx) const {\n";
752 if (Spellings.begin() != Spellings.end()) {
753 OS << " OS << \" __attribute__((" << *Spellings.begin();
754 if (Args.size()) OS << "(";
755 if (*Spellings.begin()=="availability") {
756 writeAvailabilityValue(OS);
757 } else {
758 for (ai = Args.begin(); ai != ae; ++ai) {
759 if (ai!=Args.begin()) OS <<", ";
760 (*ai)->writeValue(OS);
761 }
762 }
763 if (Args.size()) OS << ")";
764 OS << "))\";\n";
765 }
766 OS << "}\n\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000767 }
768}
769
770static void EmitAttrList(raw_ostream &OS, StringRef Class,
771 const std::vector<Record*> &AttrList) {
772 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
773
774 if (i != e) {
775 // Move the end iterator back to emit the last attribute.
776 for(--e; i != e; ++i)
777 OS << Class << "(" << (*i)->getName() << ")\n";
778
779 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
780 }
781}
782
783void ClangAttrListEmitter::run(raw_ostream &OS) {
784 OS << "// This file is generated by TableGen. Do not edit.\n\n";
785
786 OS << "#ifndef LAST_ATTR\n";
787 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
788 OS << "#endif\n\n";
789
790 OS << "#ifndef INHERITABLE_ATTR\n";
791 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
792 OS << "#endif\n\n";
793
794 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
795 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
796 OS << "#endif\n\n";
797
798 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
799 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
800 OS << "#endif\n\n";
801
802 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
803 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
804 " INHERITABLE_PARAM_ATTR(NAME)\n";
805 OS << "#endif\n\n";
806
807 Record *InhClass = Records.getClass("InheritableAttr");
808 Record *InhParamClass = Records.getClass("InheritableParamAttr");
809 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
810 NonInhAttrs, InhAttrs, InhParamAttrs;
811 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
812 i != e; ++i) {
813 if ((*i)->isSubClassOf(InhParamClass))
814 InhParamAttrs.push_back(*i);
815 else if ((*i)->isSubClassOf(InhClass))
816 InhAttrs.push_back(*i);
817 else
818 NonInhAttrs.push_back(*i);
819 }
820
821 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
822 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
823 EmitAttrList(OS, "ATTR", NonInhAttrs);
824
825 OS << "#undef LAST_ATTR\n";
826 OS << "#undef INHERITABLE_ATTR\n";
827 OS << "#undef LAST_INHERITABLE_ATTR\n";
828 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
829 OS << "#undef ATTR\n";
830}
831
832void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
833 OS << "// This file is generated by TableGen. Do not edit.\n\n";
834
835 Record *InhClass = Records.getClass("InheritableAttr");
836 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
837 ArgRecords;
838 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
839 std::vector<Argument*> Args;
840 std::vector<Argument*>::iterator ri, re;
841
842 OS << " switch (Kind) {\n";
843 OS << " default:\n";
844 OS << " assert(0 && \"Unknown attribute!\");\n";
845 OS << " break;\n";
846 for (; i != e; ++i) {
847 Record &R = **i;
848 OS << " case attr::" << R.getName() << ": {\n";
849 if (R.isSubClassOf(InhClass))
850 OS << " bool isInherited = Record[Idx++];\n";
851 ArgRecords = R.getValueAsListOfDefs("Args");
852 Args.clear();
853 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
854 Argument *A = createArgument(**ai, R.getName());
855 Args.push_back(A);
856 A->writePCHReadDecls(OS);
857 }
858 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
859 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
860 OS << ", ";
861 (*ri)->writePCHReadArgs(OS);
862 }
863 OS << ");\n";
864 if (R.isSubClassOf(InhClass))
865 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
866 OS << " break;\n";
867 OS << " }\n";
868 }
869 OS << " }\n";
870}
871
872void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
873 Record *InhClass = Records.getClass("InheritableAttr");
874 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
875 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
876
877 OS << " switch (A->getKind()) {\n";
878 OS << " default:\n";
879 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
880 OS << " break;\n";
881 for (; i != e; ++i) {
882 Record &R = **i;
883 OS << " case attr::" << R.getName() << ": {\n";
884 Args = R.getValueAsListOfDefs("Args");
885 if (R.isSubClassOf(InhClass) || !Args.empty())
886 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
887 << "Attr>(A);\n";
888 if (R.isSubClassOf(InhClass))
889 OS << " Record.push_back(SA->isInherited());\n";
890 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
891 createArgument(**ai, R.getName())->writePCHWrite(OS);
892 OS << " break;\n";
893 OS << " }\n";
894 }
895 OS << " }\n";
896}
897
898void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
899 OS << "// This file is generated by TableGen. Do not edit.\n\n";
900
901 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
902
903 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
904 Record &Attr = **I;
905
906 std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings");
907
908 for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
909 StringRef Spelling = *I;
910 OS << ".Case(\"" << Spelling << "\", true)\n";
911 }
912 }
913
914}
915
916void ClangAttrLateParsedListEmitter::run(raw_ostream &OS) {
917 OS << "// This file is generated by TableGen. Do not edit.\n\n";
918
919 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
920
921 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
922 I != E; ++I) {
923 Record &Attr = **I;
924
925 bool LateParsed = Attr.getValueAsBit("LateParsed");
926
927 if (LateParsed) {
928 std::vector<StringRef> Spellings =
929 getValueAsListOfStrings(Attr, "Spellings");
930
931 for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
932 E = Spellings.end(); I != E; ++I) {
933 OS << ".Case(\"" << (*I) << "\", " << LateParsed << ")\n";
934 }
935 }
936 }
937}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000938
939
940void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) {
941 OS << "// This file is generated by TableGen. Do not edit.\n\n";
942
943 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
944
945 OS << "Attr* instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
946 << "Sema &S,\n"
947 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
948 << " switch (At->getKind()) {\n"
949 << " default:\n"
950 << " break;\n";
951
952 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
953 I != E; ++I) {
954 Record &R = **I;
955
956 OS << " case attr::" << R.getName() << ": {\n";
957 OS << " const " << R.getName() << "Attr *A = cast<"
958 << R.getName() << "Attr>(At);\n";
959 bool TDependent = R.getValueAsBit("TemplateDependent");
960
961 if (!TDependent) {
962 OS << " return A->clone(C);\n";
963 OS << " }\n";
964 continue;
965 }
966
967 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
968 std::vector<Argument*> Args;
969 std::vector<Argument*>::iterator ai, ae;
970 Args.reserve(ArgRecords.size());
971
972 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
973 re = ArgRecords.end();
974 ri != re; ++ri) {
975 Record &ArgRecord = **ri;
976 Argument *Arg = createArgument(ArgRecord, R.getName());
977 assert(Arg);
978 Args.push_back(Arg);
979 }
980 ae = Args.end();
981
982 for (ai = Args.begin(); ai != ae; ++ai) {
983 (*ai)->writeTemplateInstantiation(OS);
984 }
985 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
986 for (ai = Args.begin(); ai != ae; ++ai) {
987 OS << ", ";
988 (*ai)->writeTemplateInstantiationArgs(OS);
989 }
990 OS << ");\n }\n";
991 }
992 OS << " } // end switch\n"
993 << " llvm_unreachable(\"Unknown attribute!\");\n"
994 << " return 0;\n"
995 << "}\n\n";
996}
997