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