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>
23 getValueAsListOfStrings(Record &R, 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", "GetType(Record[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()
175 << "= ReadString(Record, Idx);\n";
177 void writePCHReadArgs(raw_ostream &OS) const {
178 OS << getLowerName();
180 void writePCHWrite(raw_ostream &OS) const {
181 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
185 class AlignedArgument : public Argument {
187 AlignedArgument(Record &Arg, StringRef Attr)
188 : Argument(Arg, Attr)
191 void writeAccessors(raw_ostream &OS) const {
192 OS << " bool is" << getUpperName() << "Dependent() const;\n";
194 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
196 OS << " bool is" << getUpperName() << "Expr() const {\n";
197 OS << " return is" << getLowerName() << "Expr;\n";
200 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
201 OS << " assert(is" << getLowerName() << "Expr);\n";
202 OS << " return " << getLowerName() << "Expr;\n";
205 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
206 OS << " assert(!is" << getLowerName() << "Expr);\n";
207 OS << " return " << getLowerName() << "Type;\n";
210 void writeAccessorDefinitions(raw_ostream &OS) const {
211 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
212 << "Dependent() const {\n";
213 OS << " if (is" << getLowerName() << "Expr)\n";
214 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
215 << "Expr->isValueDependent() || " << getLowerName()
216 << "Expr->isTypeDependent());\n";
218 OS << " return " << getLowerName()
219 << "Type->getType()->isDependentType();\n";
222 // FIXME: Do not do the calculation here
223 // FIXME: Handle types correctly
224 // A null pointer means maximum alignment
225 // FIXME: Load the platform-specific maximum alignment, rather than
227 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
228 << "(ASTContext &Ctx) const {\n";
229 OS << " assert(!is" << getUpperName() << "Dependent());\n";
230 OS << " if (is" << getLowerName() << "Expr)\n";
231 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
232 << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)"
233 << "* Ctx.getCharWidth();\n";
235 OS << " return 0; // FIXME\n";
238 void writeCloneArgs(raw_ostream &OS) const {
239 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
240 << "Expr ? static_cast<void*>(" << getLowerName()
241 << "Expr) : " << getLowerName()
244 void writeCtorBody(raw_ostream &OS) const {
245 OS << " if (is" << getLowerName() << "Expr)\n";
246 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
247 << getUpperName() << ");\n";
249 OS << " " << getLowerName()
250 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
253 void writeCtorInitializers(raw_ostream &OS) const {
254 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
256 void writeCtorParameters(raw_ostream &OS) const {
257 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
259 void writeDeclarations(raw_ostream &OS) const {
260 OS << "bool is" << getLowerName() << "Expr;\n";
262 OS << "Expr *" << getLowerName() << "Expr;\n";
263 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
266 void writePCHReadArgs(raw_ostream &OS) const {
267 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
269 void writePCHReadDecls(raw_ostream &OS) const {
270 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
271 OS << " void *" << getLowerName() << "Ptr;\n";
272 OS << " if (is" << getLowerName() << "Expr)\n";
273 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
275 OS << " " << getLowerName()
276 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
278 void writePCHWrite(raw_ostream &OS) const {
279 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
280 OS << " if (SA->is" << getUpperName() << "Expr())\n";
281 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
283 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
284 << "Type(), Record);\n";
288 class VariadicArgument : public Argument {
292 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
293 : Argument(Arg, Attr), type(T)
296 std::string getType() const { return type; }
298 void writeAccessors(raw_ostream &OS) const {
299 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
300 OS << " " << getLowerName() << "_iterator " << getLowerName()
301 << "_begin() const {\n";
302 OS << " return " << getLowerName() << ";\n";
304 OS << " " << getLowerName() << "_iterator " << getLowerName()
305 << "_end() const {\n";
306 OS << " return " << getLowerName() << " + " << getLowerName()
309 OS << " unsigned " << getLowerName() << "_size() const {\n"
310 << " return " << getLowerName() << "Size;\n;";
313 void writeCloneArgs(raw_ostream &OS) const {
314 OS << getLowerName() << ", " << getLowerName() << "Size";
316 void writeCtorBody(raw_ostream &OS) const {
317 // FIXME: memcpy is not safe on non-trivial types.
318 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
319 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
321 void writeCtorInitializers(raw_ostream &OS) const {
322 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
323 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
324 << getLowerName() << "Size])";
326 void writeCtorParameters(raw_ostream &OS) const {
327 OS << getType() << " *" << getUpperName() << ", unsigned "
328 << getUpperName() << "Size";
330 void writeDeclarations(raw_ostream &OS) const {
331 OS << " unsigned " << getLowerName() << "Size;\n";
332 OS << " " << getType() << " *" << getLowerName() << ";";
334 void writePCHReadDecls(raw_ostream &OS) const {
335 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
336 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
338 OS << " " << getLowerName() << ".reserve(" << getLowerName()
340 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
342 std::string read = ReadPCHRecord(type);
343 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
345 void writePCHReadArgs(raw_ostream &OS) const {
346 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
348 void writePCHWrite(raw_ostream &OS) const{
349 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
350 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
351 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
352 << getLowerName() << "_end(); i != e; ++i)\n";
353 OS << " " << WritePCHRecord(type, "(*i)");
357 class EnumArgument : public Argument {
359 std::vector<StringRef> values, enums;
361 EnumArgument(Record &Arg, StringRef Attr)
362 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
363 values(getValueAsListOfStrings(Arg, "Values")),
364 enums(getValueAsListOfStrings(Arg, "Enums"))
367 void writeAccessors(raw_ostream &OS) const {
368 OS << " " << type << " get" << getUpperName() << "() const {\n";
369 OS << " return " << getLowerName() << ";\n";
372 void writeCloneArgs(raw_ostream &OS) const {
373 OS << getLowerName();
375 void writeCtorInitializers(raw_ostream &OS) const {
376 OS << getLowerName() << "(" << getUpperName() << ")";
378 void writeCtorParameters(raw_ostream &OS) const {
379 OS << type << " " << getUpperName();
381 void writeDeclarations(raw_ostream &OS) const {
382 // Calculate the various enum values
383 std::vector<StringRef> uniques(enums);
384 std::sort(uniques.begin(), uniques.end());
385 uniques.erase(std::unique(uniques.begin(), uniques.end()),
387 // FIXME: Emit a proper error
388 assert(!uniques.empty());
390 std::vector<StringRef>::iterator i = uniques.begin(),
392 // The last one needs to not have a comma.
396 OS << " enum " << type << " {\n";
398 OS << " " << *i << ",\n";
399 OS << " " << *e << "\n";
402 OS << " " << type << " " << getLowerName() << ";";
404 void writePCHReadDecls(raw_ostream &OS) const {
405 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
406 << "(static_cast<" << getAttrName() << "Attr::" << type
407 << ">(Record[Idx++]));\n";
409 void writePCHReadArgs(raw_ostream &OS) const {
410 OS << getLowerName();
412 void writePCHWrite(raw_ostream &OS) const {
413 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
418 static Argument *createArgument(Record &Arg, StringRef Attr,
419 Record *Search = 0) {
424 llvm::StringRef ArgName = Search->getName();
426 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
427 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
428 else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
430 else if (ArgName == "FunctionArgument")
431 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
432 else if (ArgName == "IdentifierArgument")
433 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
434 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
435 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
436 else if (ArgName == "TypeArgument")
437 Ptr = new SimpleArgument(Arg, Attr, "QualType");
438 else if (ArgName == "UnsignedArgument")
439 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
440 else if (ArgName == "VariadicUnsignedArgument")
441 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
444 std::vector<Record*> Bases = Search->getSuperClasses();
445 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
447 Ptr = createArgument(Arg, Attr, *i);
455 void ClangAttrClassEmitter::run(raw_ostream &OS) {
456 OS << "// This file is generated by TableGen. Do not edit.\n\n";
457 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
458 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
460 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
462 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
466 OS << "class " << R.getName() << "Attr : public Attr {\n";
468 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
469 std::vector<Argument*> Args;
470 std::vector<Argument*>::iterator ai, ae;
471 Args.reserve(ArgRecords.size());
473 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
474 re = ArgRecords.end();
476 Record &ArgRecord = **ri;
477 Argument *Arg = createArgument(ArgRecord, R.getName());
481 Arg->writeDeclarations(OS);
487 OS << "\n public:\n";
488 OS << " " << R.getName() << "Attr(SourceLocation L, ASTContext &Ctx\n";
490 for (ai = Args.begin(); ai != ae; ++ai) {
492 (*ai)->writeCtorParameters(OS);
497 OS << " : Attr(attr::" << R.getName() << ", L)\n";
499 for (ai = Args.begin(); ai != ae; ++ai) {
501 (*ai)->writeCtorInitializers(OS);
507 for (ai = Args.begin(); ai != ae; ++ai) {
508 (*ai)->writeCtorBody(OS);
513 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
515 for (ai = Args.begin(); ai != ae; ++ai) {
516 (*ai)->writeAccessors(OS);
520 OS << R.getValueAsCode("AdditionalMembers");
523 OS << " static bool classof(const Attr *A) { return A->getKind() == "
524 << "attr::" << R.getName() << "; }\n";
525 OS << " static bool classof(const " << R.getName()
526 << "Attr *) { return true; }\n";
533 void ClangAttrImplEmitter::run(raw_ostream &OS) {
534 OS << "// This file is generated by TableGen. Do not edit.\n\n";
536 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
537 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
538 std::vector<Argument*>::iterator ai, ae;
540 for (; i != e; ++i) {
542 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
543 std::vector<Argument*> Args;
544 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
545 Args.push_back(createArgument(**ri, R.getName()));
547 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
548 (*ai)->writeAccessorDefinitions(OS);
550 OS << R.getName() << "Attr *" << R.getName()
551 << "Attr::clone(ASTContext &C) const {\n";
552 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
553 for (ai = Args.begin(); ai != ae; ++ai) {
555 (*ai)->writeCloneArgs(OS);
561 void ClangAttrListEmitter::run(raw_ostream &OS) {
562 OS << "// This file is generated by TableGen. Do not edit.\n\n";
564 OS << "#ifndef LAST_ATTR\n";
565 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
568 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
569 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
572 // Move the end iterator back to emit the last attribute.
573 for(--e; i != e; ++i)
574 OS << "ATTR(" << (*i)->getName() << ")\n";
576 OS << "LAST_ATTR(" << (*i)->getName() << ")\n\n";
579 OS << "#undef LAST_ATTR\n";
580 OS << "#undef ATTR\n";
583 void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
584 OS << "// This file is generated by TableGen. Do not edit.\n\n";
586 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
588 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
589 std::vector<Argument*> Args;
590 std::vector<Argument*>::iterator ri, re;
592 OS << " switch (Kind) {\n";
594 OS << " assert(0 && \"Unknown attribute!\");\n";
596 for (; i != e; ++i) {
598 OS << " case attr::" << R.getName() << ": {\n";
599 ArgRecords = R.getValueAsListOfDefs("Args");
601 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
602 Argument *A = createArgument(**ai, R.getName());
604 A->writePCHReadDecls(OS);
606 OS << " New = new (*Context) " << R.getName() << "Attr(Loc, *Context";
607 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
609 (*ri)->writePCHReadArgs(OS);
618 void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
619 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
620 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
622 OS << " switch (A->getKind()) {\n";
624 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
626 for (; i != e; ++i) {
628 OS << " case attr::" << R.getName() << ": {\n";
629 Args = R.getValueAsListOfDefs("Args");
631 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
633 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
634 createArgument(**ai, R.getName())->writePCHWrite(OS);
641 void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
642 OS << "// This file is generated by TableGen. Do not edit.\n\n";
644 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
646 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
649 std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings");
651 for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
652 StringRef Spelling = *I;
653 OS << ".Case(\"" << Spelling << "\", true)\n";