1 //=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // These tablegen backends emit Clang AST node tables
11 //===----------------------------------------------------------------------===//
13 #include "ASTTableGen.h"
14 #include "TableGenBackends.h"
16 #include "llvm/TableGen/Error.h"
17 #include "llvm/TableGen/Record.h"
18 #include "llvm/TableGen/TableGenBackend.h"
24 using namespace clang
;
25 using namespace clang::tblgen
;
27 /// ClangASTNodesEmitter - The top-level class emits .inc files containing
28 /// declarations of Clang statements.
31 class ClangASTNodesEmitter
{
32 // A map from a node to each of its derived nodes.
33 typedef std::multimap
<ASTNode
, ASTNode
> ChildMap
;
34 typedef ChildMap::const_iterator ChildIterator
;
36 RecordKeeper
&Records
;
38 const std::string
&NodeClassName
;
39 const std::string
&BaseSuffix
;
40 std::string MacroHierarchyName
;
43 // Create a macro-ized version of a name
44 static std::string
macroName(std::string S
) {
45 for (unsigned i
= 0; i
< S
.size(); ++i
)
46 S
[i
] = std::toupper(S
[i
]);
51 const std::string
¯oHierarchyName() {
52 assert(Root
&& "root node not yet derived!");
53 if (MacroHierarchyName
.empty())
54 MacroHierarchyName
= macroName(std::string(Root
.getName()));
55 return MacroHierarchyName
;
58 // Return the name to be printed in the base field. Normally this is
59 // the record's name plus the base suffix, but if it is the root node and
60 // the suffix is non-empty, it's just the suffix.
61 std::string
baseName(ASTNode node
) {
62 if (node
== Root
&& !BaseSuffix
.empty())
65 return node
.getName().str() + BaseSuffix
;
68 void deriveChildTree();
70 std::pair
<ASTNode
, ASTNode
> EmitNode(raw_ostream
& OS
, ASTNode Base
);
72 explicit ClangASTNodesEmitter(RecordKeeper
&R
, const std::string
&N
,
74 : Records(R
), NodeClassName(N
), BaseSuffix(S
) {}
76 // run - Output the .inc file contents
77 void run(raw_ostream
&OS
);
79 } // end anonymous namespace
81 //===----------------------------------------------------------------------===//
82 // Statement Node Tables (.inc file) generation.
83 //===----------------------------------------------------------------------===//
85 // Returns the first and last non-abstract subrecords
86 // Called recursively to ensure that nodes remain contiguous
87 std::pair
<ASTNode
, ASTNode
> ClangASTNodesEmitter::EmitNode(raw_ostream
&OS
,
89 std::string BaseName
= macroName(std::string(Base
.getName()));
91 ChildIterator i
= Tree
.lower_bound(Base
), e
= Tree
.upper_bound(Base
);
92 bool HasChildren
= (i
!= e
);
95 if (!Base
.isAbstract())
99 ASTNode Child
= i
->second
;
100 bool Abstract
= Child
.isAbstract();
101 std::string NodeName
= macroName(std::string(Child
.getName()));
103 OS
<< "#ifndef " << NodeName
<< "\n";
104 OS
<< "# define " << NodeName
<< "(Type, Base) "
105 << BaseName
<< "(Type, Base)\n";
108 if (Abstract
) OS
<< "ABSTRACT_" << macroHierarchyName() << "(";
109 OS
<< NodeName
<< "(" << Child
.getName() << ", " << baseName(Base
) << ")";
110 if (Abstract
) OS
<< ")";
113 auto Result
= EmitNode(OS
, Child
);
114 assert(Result
.first
&& Result
.second
&& "node didn't have children?");
116 // Update the range of Base.
117 if (!First
) First
= Result
.first
;
118 Last
= Result
.second
;
120 OS
<< "#undef " << NodeName
<< "\n\n";
123 // If there aren't first/last nodes, it must be because there were no
124 // children and this node was abstract, which is not a sensible combination.
126 PrintFatalError(Base
.getLoc(), "abstract node has no children");
128 assert(Last
&& "set First without Last");
131 // Use FOO_RANGE unless this is the last of the ranges, in which case
132 // use LAST_FOO_RANGE.
134 OS
<< "LAST_" << macroHierarchyName() << "_RANGE(";
136 OS
<< macroHierarchyName() << "_RANGE(";
137 OS
<< Base
.getName() << ", " << First
.getName() << ", "
138 << Last
.getName() << ")\n\n";
141 return std::make_pair(First
, Last
);
144 void ClangASTNodesEmitter::deriveChildTree() {
145 assert(!Root
&& "already computed tree");
148 const std::vector
<Record
*> Stmts
149 = Records
.getAllDerivedDefinitions(NodeClassName
);
151 for (unsigned i
= 0, e
= Stmts
.size(); i
!= e
; ++i
) {
152 Record
*R
= Stmts
[i
];
154 if (auto B
= R
->getValueAsOptionalDef(BaseFieldName
))
155 Tree
.insert(std::make_pair(B
, R
));
157 PrintFatalError(R
->getLoc(),
158 Twine("multiple root nodes in \"") + NodeClassName
165 PrintFatalError(Twine("didn't find root node in \"") + NodeClassName
169 void ClangASTNodesEmitter::run(raw_ostream
&OS
) {
172 emitSourceFileHeader("List of AST nodes of a particular kind", OS
, Records
);
174 // Write the preamble
175 OS
<< "#ifndef ABSTRACT_" << macroHierarchyName() << "\n";
176 OS
<< "# define ABSTRACT_" << macroHierarchyName() << "(Type) Type\n";
179 OS
<< "#ifndef " << macroHierarchyName() << "_RANGE\n";
181 << macroHierarchyName() << "_RANGE(Base, First, Last)\n";
184 OS
<< "#ifndef LAST_" << macroHierarchyName() << "_RANGE\n";
185 OS
<< "# define LAST_"
186 << macroHierarchyName() << "_RANGE(Base, First, Last) "
187 << macroHierarchyName() << "_RANGE(Base, First, Last)\n";
192 OS
<< "#undef " << macroHierarchyName() << "\n";
193 OS
<< "#undef " << macroHierarchyName() << "_RANGE\n";
194 OS
<< "#undef LAST_" << macroHierarchyName() << "_RANGE\n";
195 OS
<< "#undef ABSTRACT_" << macroHierarchyName() << "\n";
198 void clang::EmitClangASTNodes(RecordKeeper
&RK
, raw_ostream
&OS
,
199 const std::string
&N
, const std::string
&S
) {
200 ClangASTNodesEmitter(RK
, N
, S
).run(OS
);
203 // Emits and addendum to a .inc file to enumerate the clang declaration
205 void clang::EmitClangDeclContext(RecordKeeper
&Records
, raw_ostream
&OS
) {
206 // FIXME: Find a .td file format to allow for this to be represented better.
208 emitSourceFileHeader("List of AST Decl nodes", OS
, Records
);
210 OS
<< "#ifndef DECL_CONTEXT\n";
211 OS
<< "# define DECL_CONTEXT(DECL)\n";
214 OS
<< "#ifndef DECL_CONTEXT_BASE\n";
215 OS
<< "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n";
218 typedef std::set
<Record
*> RecordSet
;
219 typedef std::vector
<Record
*> RecordVector
;
221 RecordVector DeclContextsVector
222 = Records
.getAllDerivedDefinitions(DeclContextNodeClassName
);
223 RecordVector Decls
= Records
.getAllDerivedDefinitions(DeclNodeClassName
);
224 RecordSet
DeclContexts (DeclContextsVector
.begin(), DeclContextsVector
.end());
226 for (RecordVector::iterator i
= Decls
.begin(), e
= Decls
.end(); i
!= e
; ++i
) {
229 if (Record
*B
= R
->getValueAsOptionalDef(BaseFieldName
)) {
230 if (DeclContexts
.find(B
) != DeclContexts
.end()) {
231 OS
<< "DECL_CONTEXT_BASE(" << B
->getName() << ")\n";
232 DeclContexts
.erase(B
);
237 // To keep identical order, RecordVector may be used
238 // instead of RecordSet.
239 for (RecordVector::iterator
240 i
= DeclContextsVector
.begin(), e
= DeclContextsVector
.end();
242 if (DeclContexts
.find(*i
) != DeclContexts
.end())
243 OS
<< "DECL_CONTEXT(" << (*i
)->getName() << ")\n";
245 OS
<< "#undef DECL_CONTEXT\n";
246 OS
<< "#undef DECL_CONTEXT_BASE\n";