1
//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
10
// These tablegen backends emit Clang attribute processing code
12
//===----------------------------------------------------------------------===//
14
#include "ClangAttrEmitter.h"
16
#include "llvm/ADT/StringSwitch.h"
22
static const std::vector<StringRef> getValueAsListOfStrings(Record &R,
23
StringRef FieldName) {
24
ListInit *List = R.getValueAsListInit(FieldName);
25
assert (List && "Got a null ListInit");
27
std::vector<StringRef> Strings;
28
Strings.reserve(List->getSize());
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());
37
assert(false && "Got a non-string, non-code element in a ListInit");
43
std::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++]))")
47
.Case("QualType", "ReadTypeRecord(Idx++)")
48
.Default("Record[Idx++]");
51
// Assumes that the way to get the value is SA->getname()
52
std::string WritePCHRecord(StringRef type, StringRef name) {
53
return StringSwitch<std::string>(type)
54
.EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
56
.Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
57
.Default("Record.push_back(" + std::string(name) + ");\n");
62
std::string lowerName, upperName;
66
Argument(Record &Arg, StringRef Attr)
67
: lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
69
if (!lowerName.empty()) {
70
lowerName[0] = std::tolower(lowerName[0]);
71
upperName[0] = std::toupper(upperName[0]);
74
virtual ~Argument() {}
76
StringRef getLowerName() const { return lowerName; }
77
StringRef getUpperName() const { return upperName; }
78
StringRef getAttrName() const { return attrName; }
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;
93
class SimpleArgument : public Argument {
97
SimpleArgument(Record &Arg, StringRef Attr, std::string T)
98
: Argument(Arg, Attr), type(T)
101
void writeAccessors(raw_ostream &OS) const {
102
OS << " " << type << " get" << getUpperName() << "() const {\n";
103
OS << " return " << getLowerName() << ";\n";
106
void writeCloneArgs(raw_ostream &OS) const {
107
OS << getLowerName();
109
void writeCtorInitializers(raw_ostream &OS) const {
110
OS << getLowerName() << "(" << getUpperName() << ")";
112
void writeCtorParameters(raw_ostream &OS) const {
113
OS << type << " " << getUpperName();
115
void writeDeclarations(raw_ostream &OS) const {
116
OS << type << " " << getLowerName() << ";";
118
void writePCHReadDecls(raw_ostream &OS) const {
119
std::string read = ReadPCHRecord(type);
120
OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
122
void writePCHReadArgs(raw_ostream &OS) const {
123
OS << getLowerName();
125
void writePCHWrite(raw_ostream &OS) const {
126
OS << " " << WritePCHRecord(type, "SA->get" +
127
std::string(getUpperName()) + "()");
131
class StringArgument : public Argument {
133
StringArgument(Record &Arg, StringRef Attr)
134
: Argument(Arg, Attr)
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";
142
OS << " unsigned get" << getUpperName() << "Length() const {\n";
143
OS << " return " << getLowerName() << "Length;\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";
154
void writeCloneArgs(raw_ostream &OS) const {
155
OS << "get" << getUpperName() << "()";
157
void writeCtorBody(raw_ostream &OS) const {
158
OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
159
<< ".data(), " << getLowerName() << "Length);";
161
void writeCtorInitializers(raw_ostream &OS) const {
162
OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
163
<< getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
166
void writeCtorParameters(raw_ostream &OS) const {
167
OS << "llvm::StringRef " << getUpperName();
169
void writeDeclarations(raw_ostream &OS) const {
170
OS << "unsigned " << getLowerName() << "Length;\n";
171
OS << "char *" << getLowerName() << ";";
173
void writePCHReadDecls(raw_ostream &OS) const {
174
OS << " std::string " << getLowerName() << "= ReadString(Record, Idx);\n";
176
void writePCHReadArgs(raw_ostream &OS) const {
177
OS << getLowerName();
179
void writePCHWrite(raw_ostream &OS) const {
180
OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
184
class AlignedArgument : public Argument {
186
AlignedArgument(Record &Arg, StringRef Attr)
187
: Argument(Arg, Attr)
190
void writeAccessors(raw_ostream &OS) const {
191
OS << " bool is" << getUpperName() << "Dependent() const;\n";
193
OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
195
OS << " bool is" << getUpperName() << "Expr() const {\n";
196
OS << " return is" << getLowerName() << "Expr;\n";
199
OS << " Expr *get" << getUpperName() << "Expr() const {\n";
200
OS << " assert(is" << getLowerName() << "Expr);\n";
201
OS << " return " << getLowerName() << "Expr;\n";
204
OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
205
OS << " assert(!is" << getLowerName() << "Expr);\n";
206
OS << " return " << getLowerName() << "Type;\n";
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";
217
OS << " return " << getLowerName()
218
<< "Type->getType()->isDependentType();\n";
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
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";
234
OS << " return 0; // FIXME\n";
237
void writeCloneArgs(raw_ostream &OS) const {
238
OS << "is" << getLowerName() << "Expr, is" << getLowerName()
239
<< "Expr ? static_cast<void*>(" << getLowerName()
240
<< "Expr) : " << getLowerName()
243
void writeCtorBody(raw_ostream &OS) const {
244
OS << " if (is" << getLowerName() << "Expr)\n";
245
OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
246
<< getUpperName() << ");\n";
248
OS << " " << getLowerName()
249
<< "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
252
void writeCtorInitializers(raw_ostream &OS) const {
253
OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
255
void writeCtorParameters(raw_ostream &OS) const {
256
OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
258
void writeDeclarations(raw_ostream &OS) const {
259
OS << "bool is" << getLowerName() << "Expr;\n";
261
OS << "Expr *" << getLowerName() << "Expr;\n";
262
OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
265
void writePCHReadArgs(raw_ostream &OS) const {
266
OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
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";
274
OS << " " << getLowerName()
275
<< "Ptr = GetTypeSourceInfo(DeclsCursor, Record, Idx);\n";
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";
282
OS << " AddTypeSourceInfo(SA->get" << getUpperName()
283
<< "Type(), Record);\n";
287
class VariadicArgument : public Argument {
291
VariadicArgument(Record &Arg, StringRef Attr, std::string T)
292
: Argument(Arg, Attr), type(T)
295
std::string getType() const { return type; }
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";
303
OS << " " << getLowerName() << "_iterator " << getLowerName()
304
<< "_end() const {\n";
305
OS << " return " << getLowerName() << " + " << getLowerName()
308
OS << " unsigned " << getLowerName() << "_size() const {\n"
309
<< " return " << getLowerName() << "Size;\n;";
312
void writeCloneArgs(raw_ostream &OS) const {
313
OS << getLowerName() << ", " << getLowerName() << "Size";
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";
320
void writeCtorInitializers(raw_ostream &OS) const {
321
OS << getLowerName() << "Size(" << getUpperName() << "Size), "
322
<< getLowerName() << "(new (Ctx, 16) " << getType() << "["
323
<< getLowerName() << "Size])";
325
void writeCtorParameters(raw_ostream &OS) const {
326
OS << getType() << " *" << getUpperName() << ", unsigned "
327
<< getUpperName() << "Size";
329
void writeDeclarations(raw_ostream &OS) const {
330
OS << " unsigned " << getLowerName() << "Size;\n";
331
OS << " " << getType() << " *" << getLowerName() << ";";
333
void writePCHReadDecls(raw_ostream &OS) const {
334
OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
335
OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
337
OS << " " << getLowerName() << ".reserve(" << getLowerName()
339
OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
341
std::string read = ReadPCHRecord(type);
342
OS << " " << getLowerName() << ".push_back(" << read << ");\n";
344
void writePCHReadArgs(raw_ostream &OS) const {
345
OS << getLowerName() << ".data(), " << getLowerName() << "Size";
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)");
356
class EnumArgument : public Argument {
358
std::vector<StringRef> values, enums;
360
EnumArgument(Record &Arg, StringRef Attr)
361
: Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
362
values(getValueAsListOfStrings(Arg, "Values")),
363
enums(getValueAsListOfStrings(Arg, "Enums"))
366
void writeAccessors(raw_ostream &OS) const {
367
OS << " " << type << " get" << getUpperName() << "() const {\n";
368
OS << " return " << getLowerName() << ";\n";
371
void writeCloneArgs(raw_ostream &OS) const {
372
OS << getLowerName();
374
void writeCtorInitializers(raw_ostream &OS) const {
375
OS << getLowerName() << "(" << getUpperName() << ")";
377
void writeCtorParameters(raw_ostream &OS) const {
378
OS << type << " " << getUpperName();
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()),
386
// FIXME: Emit a proper error
387
assert(!uniques.empty());
389
std::vector<StringRef>::iterator i = uniques.begin(),
391
// The last one needs to not have a comma.
395
OS << " enum " << type << " {\n";
397
OS << " " << *i << ",\n";
398
OS << " " << *e << "\n";
401
OS << " " << type << " " << getLowerName() << ";";
403
void writePCHReadDecls(raw_ostream &OS) const {
404
OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
405
<< "(static_cast<" << getAttrName() << "Attr::" << type
406
<< ">(Record[Idx++]));\n";
408
void writePCHReadArgs(raw_ostream &OS) const {
409
OS << getLowerName();
411
void writePCHWrite(raw_ostream &OS) const {
412
OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
417
static Argument *createArgument(Record &Arg, StringRef Attr,
418
Record *Search = 0) {
423
llvm::StringRef ArgName = Search->getName();
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,
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");
443
std::vector<Record*> Bases = Search->getSuperClasses();
444
for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
446
Ptr = createArgument(Arg, Attr, *i);
454
void 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";
459
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
461
for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
465
OS << "class " << R.getName() << "Attr : public Attr {\n";
467
std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
468
std::vector<Argument*> Args;
469
std::vector<Argument*>::iterator ai, ae;
470
Args.reserve(ArgRecords.size());
472
for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
473
re = ArgRecords.end();
475
Record &ArgRecord = **ri;
476
Argument *Arg = createArgument(ArgRecord, R.getName());
480
Arg->writeDeclarations(OS);
486
OS << "\n public:\n";
487
OS << " " << R.getName() << "Attr(SourceLocation L, ASTContext &Ctx\n";
489
for (ai = Args.begin(); ai != ae; ++ai) {
491
(*ai)->writeCtorParameters(OS);
496
OS << " : Attr(attr::" << R.getName() << ", L)\n";
498
for (ai = Args.begin(); ai != ae; ++ai) {
500
(*ai)->writeCtorInitializers(OS);
506
for (ai = Args.begin(); ai != ae; ++ai) {
507
(*ai)->writeCtorBody(OS);
512
OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
514
for (ai = Args.begin(); ai != ae; ++ai) {
515
(*ai)->writeAccessors(OS);
519
OS << R.getValueAsCode("AdditionalMembers");
522
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";
532
void ClangAttrImplEmitter::run(raw_ostream &OS) {
533
OS << "// This file is generated by TableGen. Do not edit.\n\n";
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;
539
for (; i != e; ++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()));
546
for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
547
(*ai)->writeAccessorDefinitions(OS);
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) {
554
(*ai)->writeCloneArgs(OS);
560
void ClangAttrListEmitter::run(raw_ostream &OS) {
561
OS << "// This file is generated by TableGen. Do not edit.\n\n";
563
OS << "#ifndef LAST_ATTR\n";
564
OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
567
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
568
std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
571
// Move the end iterator back to emit the last attribute.
572
for(--e; i != e; ++i)
573
OS << "ATTR(" << (*i)->getName() << ")\n";
575
OS << "LAST_ATTR(" << (*i)->getName() << ")\n\n";
578
OS << "#undef LAST_ATTR\n";
579
OS << "#undef ATTR\n";
582
void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
583
OS << "// This file is generated by TableGen. Do not edi.\n\n";
585
std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
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;
591
OS << " switch (Kind) {\n";
593
OS << " assert(0 && \"Unknown attribute!\");\n";
595
for (; i != e; ++i) {
597
OS << " case attr::" << R.getName() << ": {\n";
598
ArgRecords = R.getValueAsListOfDefs("Args");
600
for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
601
Argument *A = createArgument(**ai, R.getName());
603
A->writePCHReadDecls(OS);
605
OS << " New = new (*Context) " << R.getName() << "Attr(Loc, *Context";
606
for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
608
(*ri)->writePCHReadArgs(OS);
617
void 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;
621
OS << " switch (A->getKind()) {\n";
623
OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
625
for (; i != e; ++i) {
627
OS << " case attr::" << R.getName() << ": {\n";
628
Args = R.getValueAsListOfDefs("Args");
630
OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
632
for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
633
createArgument(**ai, R.getName())->writePCHWrite(OS);