Add an emitter to handle the list of clang statement nodes.
[oota-llvm.git] / utils / TableGen / ClangASTNodesEmitter.cpp
1 #include "ClangASTNodesEmitter.h"
2 #include "Record.h"
3 #include <vector>
4 #include <stack>
5 #include <string>
6 #include <map>
7 #include <utility>
8 #include <clocale>
9 using namespace llvm;
10
11 //===----------------------------------------------------------------------===//
12 // Statement Node Tables (.inc file) generation.
13 //===----------------------------------------------------------------------===//
14
15 // Sort to create a tree-like structure based on the 'Base' field.
16 namespace {
17   // Create a macro-ized version of a name
18   std::string macroName(std::string S) {
19     for (unsigned i = 0; i < S.size(); ++i)
20       S[i] = std::toupper(S[i]);
21
22     return S;
23   }
24
25   // A map from a node to each of its derived nodes.
26   typedef std::multimap<Record*, Record*> ChildMap;
27   typedef ChildMap::const_iterator ChildIterator;
28
29   // Returns the first and last non-abstract subrecords
30   std::pair<Record *, Record *> EmitStmtNode(const ChildMap &Tree,
31                                              raw_ostream &OS, Record *Base) {
32     std::string BaseName = macroName(Base->getName());
33
34     ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
35
36     Record *First = 0, *Last = 0;
37     // This might be the pseudo-node for Stmt; don't assume it has an Abstract
38     // bit
39     if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract"))
40       First = Last = Base;
41
42     for (; i != e; ++i) {
43       Record *R = i->second;
44       bool Abstract = R->getValueAsBit("Abstract");
45       std::string NodeName = macroName(R->getName());
46
47       OS << "#ifndef " << NodeName << "\n";
48       OS << "#  define " << NodeName << "(Type, Base) "
49          << BaseName << "(Type, Base)\n";
50       OS << "#endif\n";
51
52       if (Abstract)
53         OS << "ABSTRACT(" << NodeName << "(" << R->getName() << ", "
54            << Base->getName() << "))\n";
55       else
56         OS << NodeName << "(" << R->getName() << ", "
57            << Base->getName() << ")\n";
58
59       if (Tree.find(R) != Tree.end()) {
60         const std::pair<Record *, Record *> &Result = EmitStmtNode(Tree, OS, R);
61         if (!First && Result.first)
62           First = Result.first;
63         if (Result.second)
64           Last = Result.second;
65       } else {
66         if (!Abstract) {
67           Last = R;
68
69           if (!First)
70             First = R;
71         }
72       }
73
74       OS << "#undef " << NodeName << "\n\n";
75     }
76
77     assert(!First == !Last && "Got a first or last node, but not the other");
78
79     if (First) {
80       OS << "#ifndef FIRST_" << BaseName << "\n";
81       OS << "#  define FIRST_" << BaseName << "(CLASS)\n";
82       OS << "#endif\n";
83       OS << "#ifndef LAST_" << BaseName << "\n";
84       OS << "#  define LAST_" << BaseName << "(CLASS)\n";
85       OS << "#endif\n\n";
86
87       OS << "FIRST_" << BaseName << "(" << First->getName() << ")\n";
88       OS << "LAST_" << BaseName << "(" << Last->getName() << ")\n\n";
89     }
90
91     OS << "#undef FIRST_" << BaseName << "\n";
92     OS << "#undef LAST_" << BaseName << "\n\n";
93
94     return std::make_pair(First, Last);
95   }
96 }
97
98 void ClangStmtNodesEmitter::run(raw_ostream &OS) {
99   // Write the preamble
100   OS << "#ifndef ABSTRACT\n";
101   OS << "#  define ABSTRACT(Stmt) Stmt\n";
102   OS << "#endif\n\n";
103
104   // Emit statements
105   const std::vector<Record*> Stmts = Records.getAllDerivedDefinitions("Stmt");
106
107   ChildMap Tree;
108
109   // Create a pseudo-record to serve as the Stmt node, which isn't actually
110   // output.
111   Record Stmt ("Stmt", SMLoc());
112
113   for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
114     Record *R = Stmts[i];
115
116     if (R->getValue("Base"))
117       Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
118     else
119       Tree.insert(std::make_pair(&Stmt, R));
120   }
121
122   EmitStmtNode(Tree, OS, &Stmt);
123
124   OS << "#undef STMT\n";
125   OS << "#undef ABSTRACT\n";
126 }