xref: /freebsd/contrib/llvm-project/clang/utils/TableGen/ClangASTNodesEmitter.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
10b57cec5SDimitry Andric //=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // These tablegen backends emit Clang AST node tables
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
13480093f4SDimitry Andric #include "ASTTableGen.h"
14a7dea167SDimitry Andric #include "TableGenBackends.h"
15a7dea167SDimitry Andric 
16480093f4SDimitry Andric #include "llvm/TableGen/Error.h"
170b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
180b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
190b57cec5SDimitry Andric #include <cctype>
200b57cec5SDimitry Andric #include <map>
210b57cec5SDimitry Andric #include <set>
220b57cec5SDimitry Andric #include <string>
230b57cec5SDimitry Andric using namespace llvm;
24480093f4SDimitry Andric using namespace clang;
25480093f4SDimitry Andric using namespace clang::tblgen;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric /// ClangASTNodesEmitter - The top-level class emits .inc files containing
280b57cec5SDimitry Andric ///  declarations of Clang statements.
290b57cec5SDimitry Andric ///
300b57cec5SDimitry Andric namespace {
310b57cec5SDimitry Andric class ClangASTNodesEmitter {
320b57cec5SDimitry Andric   // A map from a node to each of its derived nodes.
33480093f4SDimitry Andric   typedef std::multimap<ASTNode, ASTNode> ChildMap;
340b57cec5SDimitry Andric   typedef ChildMap::const_iterator ChildIterator;
350b57cec5SDimitry Andric 
36*1db9f3b2SDimitry Andric   std::set<ASTNode> PrioritizedClasses;
370b57cec5SDimitry Andric   RecordKeeper &Records;
38480093f4SDimitry Andric   ASTNode Root;
39480093f4SDimitry Andric   const std::string &NodeClassName;
400b57cec5SDimitry Andric   const std::string &BaseSuffix;
41480093f4SDimitry Andric   std::string MacroHierarchyName;
42480093f4SDimitry Andric   ChildMap Tree;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   // Create a macro-ized version of a name
450b57cec5SDimitry Andric   static std::string macroName(std::string S) {
460b57cec5SDimitry Andric     for (unsigned i = 0; i < S.size(); ++i)
470b57cec5SDimitry Andric       S[i] = std::toupper(S[i]);
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric     return S;
500b57cec5SDimitry Andric   }
510b57cec5SDimitry Andric 
52480093f4SDimitry Andric   const std::string &macroHierarchyName() {
53480093f4SDimitry Andric     assert(Root && "root node not yet derived!");
54480093f4SDimitry Andric     if (MacroHierarchyName.empty())
555ffd83dbSDimitry Andric       MacroHierarchyName = macroName(std::string(Root.getName()));
56480093f4SDimitry Andric     return MacroHierarchyName;
57480093f4SDimitry Andric   }
58480093f4SDimitry Andric 
590b57cec5SDimitry Andric   // Return the name to be printed in the base field. Normally this is
600b57cec5SDimitry Andric   // the record's name plus the base suffix, but if it is the root node and
610b57cec5SDimitry Andric   // the suffix is non-empty, it's just the suffix.
62480093f4SDimitry Andric   std::string baseName(ASTNode node) {
63480093f4SDimitry Andric     if (node == Root && !BaseSuffix.empty())
640b57cec5SDimitry Andric       return BaseSuffix;
650b57cec5SDimitry Andric 
66480093f4SDimitry Andric     return node.getName().str() + BaseSuffix;
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric 
69480093f4SDimitry Andric   void deriveChildTree();
70480093f4SDimitry Andric 
71480093f4SDimitry Andric   std::pair<ASTNode, ASTNode> EmitNode(raw_ostream& OS, ASTNode Base);
720b57cec5SDimitry Andric public:
730b57cec5SDimitry Andric   explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N,
74*1db9f3b2SDimitry Andric                                 const std::string &S,
75*1db9f3b2SDimitry Andric                                 std::string_view PriorizeIfSubclassOf)
76*1db9f3b2SDimitry Andric       : Records(R), NodeClassName(N), BaseSuffix(S) {
77*1db9f3b2SDimitry Andric     auto vecPrioritized =
78*1db9f3b2SDimitry Andric         PriorizeIfSubclassOf.empty()
79*1db9f3b2SDimitry Andric             ? std::vector<Record *>{}
80*1db9f3b2SDimitry Andric             : R.getAllDerivedDefinitions(PriorizeIfSubclassOf);
81*1db9f3b2SDimitry Andric     PrioritizedClasses =
82*1db9f3b2SDimitry Andric         std::set<ASTNode>(vecPrioritized.begin(), vecPrioritized.end());
83*1db9f3b2SDimitry Andric   }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   // run - Output the .inc file contents
860b57cec5SDimitry Andric   void run(raw_ostream &OS);
870b57cec5SDimitry Andric };
880b57cec5SDimitry Andric } // end anonymous namespace
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
910b57cec5SDimitry Andric // Statement Node Tables (.inc file) generation.
920b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric // Returns the first and last non-abstract subrecords
950b57cec5SDimitry Andric // Called recursively to ensure that nodes remain contiguous
96480093f4SDimitry Andric std::pair<ASTNode, ASTNode> ClangASTNodesEmitter::EmitNode(raw_ostream &OS,
97480093f4SDimitry Andric                                                            ASTNode Base) {
985ffd83dbSDimitry Andric   std::string BaseName = macroName(std::string(Base.getName()));
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
101480093f4SDimitry Andric   bool HasChildren = (i != e);
1020b57cec5SDimitry Andric 
103480093f4SDimitry Andric   ASTNode First, Last;
104480093f4SDimitry Andric   if (!Base.isAbstract())
1050b57cec5SDimitry Andric     First = Last = Base;
1060b57cec5SDimitry Andric 
107*1db9f3b2SDimitry Andric   auto comp = [this](ASTNode LHS, ASTNode RHS) {
108*1db9f3b2SDimitry Andric     auto LHSPrioritized = PrioritizedClasses.count(LHS) > 0;
109*1db9f3b2SDimitry Andric     auto RHSPrioritized = PrioritizedClasses.count(RHS) > 0;
110*1db9f3b2SDimitry Andric     if (LHSPrioritized && !RHSPrioritized)
111*1db9f3b2SDimitry Andric       return true;
112*1db9f3b2SDimitry Andric     if (!LHSPrioritized && RHSPrioritized)
113*1db9f3b2SDimitry Andric       return false;
114*1db9f3b2SDimitry Andric 
115*1db9f3b2SDimitry Andric     return LHS.getName() > RHS.getName();
116*1db9f3b2SDimitry Andric   };
117*1db9f3b2SDimitry Andric   auto SortedChildren = std::set<ASTNode, decltype(comp)>(comp);
118*1db9f3b2SDimitry Andric 
1190b57cec5SDimitry Andric   for (; i != e; ++i) {
120*1db9f3b2SDimitry Andric     SortedChildren.insert(i->second);
121*1db9f3b2SDimitry Andric   }
122*1db9f3b2SDimitry Andric 
123*1db9f3b2SDimitry Andric   for (const auto &Child : SortedChildren) {
124480093f4SDimitry Andric     bool Abstract = Child.isAbstract();
1255ffd83dbSDimitry Andric     std::string NodeName = macroName(std::string(Child.getName()));
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     OS << "#ifndef " << NodeName << "\n";
1280b57cec5SDimitry Andric     OS << "#  define " << NodeName << "(Type, Base) "
1290b57cec5SDimitry Andric         << BaseName << "(Type, Base)\n";
1300b57cec5SDimitry Andric     OS << "#endif\n";
1310b57cec5SDimitry Andric 
132480093f4SDimitry Andric     if (Abstract) OS << "ABSTRACT_" << macroHierarchyName() << "(";
133480093f4SDimitry Andric     OS << NodeName << "(" << Child.getName() << ", " << baseName(Base) << ")";
134480093f4SDimitry Andric     if (Abstract) OS << ")";
135480093f4SDimitry Andric     OS << "\n";
1360b57cec5SDimitry Andric 
137480093f4SDimitry Andric     auto Result = EmitNode(OS, Child);
138480093f4SDimitry Andric     assert(Result.first && Result.second && "node didn't have children?");
139480093f4SDimitry Andric 
140480093f4SDimitry Andric     // Update the range of Base.
141480093f4SDimitry Andric     if (!First) First = Result.first;
1420b57cec5SDimitry Andric     Last = Result.second;
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric     OS << "#undef " << NodeName << "\n\n";
1450b57cec5SDimitry Andric   }
1460b57cec5SDimitry Andric 
147480093f4SDimitry Andric   // If there aren't first/last nodes, it must be because there were no
148480093f4SDimitry Andric   // children and this node was abstract, which is not a sensible combination.
149480093f4SDimitry Andric   if (!First) {
150480093f4SDimitry Andric     PrintFatalError(Base.getLoc(), "abstract node has no children");
151480093f4SDimitry Andric   }
152480093f4SDimitry Andric   assert(Last && "set First without Last");
153480093f4SDimitry Andric 
154480093f4SDimitry Andric   if (HasChildren) {
155480093f4SDimitry Andric     // Use FOO_RANGE unless this is the last of the ranges, in which case
156480093f4SDimitry Andric     // use LAST_FOO_RANGE.
157480093f4SDimitry Andric     if (Base == Root)
158480093f4SDimitry Andric       OS << "LAST_" << macroHierarchyName() << "_RANGE(";
1590b57cec5SDimitry Andric     else
160480093f4SDimitry Andric       OS << macroHierarchyName() << "_RANGE(";
161480093f4SDimitry Andric     OS << Base.getName() << ", " << First.getName() << ", "
162480093f4SDimitry Andric        << Last.getName() << ")\n\n";
1630b57cec5SDimitry Andric   }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   return std::make_pair(First, Last);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric 
168480093f4SDimitry Andric void ClangASTNodesEmitter::deriveChildTree() {
169480093f4SDimitry Andric   assert(!Root && "already computed tree");
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   // Emit statements
1720b57cec5SDimitry Andric   const std::vector<Record*> Stmts
173480093f4SDimitry Andric     = Records.getAllDerivedDefinitions(NodeClassName);
1740b57cec5SDimitry Andric 
175*1db9f3b2SDimitry Andric   for (auto *R : Stmts) {
176480093f4SDimitry Andric     if (auto B = R->getValueAsOptionalDef(BaseFieldName))
177480093f4SDimitry Andric       Tree.insert(std::make_pair(B, R));
178480093f4SDimitry Andric     else if (Root)
179480093f4SDimitry Andric       PrintFatalError(R->getLoc(),
180480093f4SDimitry Andric                       Twine("multiple root nodes in \"") + NodeClassName
181480093f4SDimitry Andric                         + "\" hierarchy");
1820b57cec5SDimitry Andric     else
183480093f4SDimitry Andric       Root = R;
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
186480093f4SDimitry Andric   if (!Root)
187480093f4SDimitry Andric     PrintFatalError(Twine("didn't find root node in \"") + NodeClassName
188480093f4SDimitry Andric                       + "\" hierarchy");
189480093f4SDimitry Andric }
1900b57cec5SDimitry Andric 
191480093f4SDimitry Andric void ClangASTNodesEmitter::run(raw_ostream &OS) {
192480093f4SDimitry Andric   deriveChildTree();
193480093f4SDimitry Andric 
1945f757f3fSDimitry Andric   emitSourceFileHeader("List of AST nodes of a particular kind", OS, Records);
195480093f4SDimitry Andric 
196480093f4SDimitry Andric   // Write the preamble
197480093f4SDimitry Andric   OS << "#ifndef ABSTRACT_" << macroHierarchyName() << "\n";
198480093f4SDimitry Andric   OS << "#  define ABSTRACT_" << macroHierarchyName() << "(Type) Type\n";
199480093f4SDimitry Andric   OS << "#endif\n";
200480093f4SDimitry Andric 
201480093f4SDimitry Andric   OS << "#ifndef " << macroHierarchyName() << "_RANGE\n";
202480093f4SDimitry Andric   OS << "#  define "
203480093f4SDimitry Andric      << macroHierarchyName() << "_RANGE(Base, First, Last)\n";
204480093f4SDimitry Andric   OS << "#endif\n\n";
205480093f4SDimitry Andric 
206480093f4SDimitry Andric   OS << "#ifndef LAST_" << macroHierarchyName() << "_RANGE\n";
207*1db9f3b2SDimitry Andric   OS << "#  define LAST_" << macroHierarchyName()
208*1db9f3b2SDimitry Andric      << "_RANGE(Base, First, Last) " << macroHierarchyName()
209*1db9f3b2SDimitry Andric      << "_RANGE(Base, First, Last)\n";
210480093f4SDimitry Andric   OS << "#endif\n\n";
211480093f4SDimitry Andric 
212480093f4SDimitry Andric   EmitNode(OS, Root);
213480093f4SDimitry Andric 
214480093f4SDimitry Andric   OS << "#undef " << macroHierarchyName() << "\n";
215480093f4SDimitry Andric   OS << "#undef " << macroHierarchyName() << "_RANGE\n";
216480093f4SDimitry Andric   OS << "#undef LAST_" << macroHierarchyName() << "_RANGE\n";
217480093f4SDimitry Andric   OS << "#undef ABSTRACT_" << macroHierarchyName() << "\n";
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric 
220a7dea167SDimitry Andric void clang::EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
221*1db9f3b2SDimitry Andric                               const std::string &N, const std::string &S,
222*1db9f3b2SDimitry Andric                               std::string_view PriorizeIfSubclassOf) {
223*1db9f3b2SDimitry Andric   ClangASTNodesEmitter(RK, N, S, PriorizeIfSubclassOf).run(OS);
224*1db9f3b2SDimitry Andric }
225*1db9f3b2SDimitry Andric 
226*1db9f3b2SDimitry Andric void printDeclContext(const std::multimap<Record *, Record *> &Tree,
227*1db9f3b2SDimitry Andric                       Record *DeclContext, raw_ostream &OS) {
228*1db9f3b2SDimitry Andric   if (!DeclContext->getValueAsBit(AbstractFieldName))
229*1db9f3b2SDimitry Andric     OS << "DECL_CONTEXT(" << DeclContext->getName() << ")\n";
230*1db9f3b2SDimitry Andric   auto i = Tree.lower_bound(DeclContext);
231*1db9f3b2SDimitry Andric   auto end = Tree.upper_bound(DeclContext);
232*1db9f3b2SDimitry Andric   for (; i != end; ++i) {
233*1db9f3b2SDimitry Andric     printDeclContext(Tree, i->second, OS);
234*1db9f3b2SDimitry Andric   }
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric // Emits and addendum to a .inc file to enumerate the clang declaration
2380b57cec5SDimitry Andric // contexts.
239a7dea167SDimitry Andric void clang::EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) {
2400b57cec5SDimitry Andric   // FIXME: Find a .td file format to allow for this to be represented better.
2410b57cec5SDimitry Andric 
2425f757f3fSDimitry Andric   emitSourceFileHeader("List of AST Decl nodes", OS, Records);
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   OS << "#ifndef DECL_CONTEXT\n";
2450b57cec5SDimitry Andric   OS << "#  define DECL_CONTEXT(DECL)\n";
2460b57cec5SDimitry Andric   OS << "#endif\n";
2470b57cec5SDimitry Andric 
248*1db9f3b2SDimitry Andric   std::vector<Record *> DeclContextsVector =
249*1db9f3b2SDimitry Andric       Records.getAllDerivedDefinitions(DeclContextNodeClassName);
250*1db9f3b2SDimitry Andric   std::vector<Record *> Decls =
251*1db9f3b2SDimitry Andric       Records.getAllDerivedDefinitions(DeclNodeClassName);
2520b57cec5SDimitry Andric 
253*1db9f3b2SDimitry Andric   std::multimap<Record *, Record *> Tree;
2540b57cec5SDimitry Andric 
255*1db9f3b2SDimitry Andric   const std::vector<Record *> Stmts =
256*1db9f3b2SDimitry Andric       Records.getAllDerivedDefinitions(DeclNodeClassName);
2570b57cec5SDimitry Andric 
258*1db9f3b2SDimitry Andric   for (auto *R : Stmts) {
259*1db9f3b2SDimitry Andric     if (auto *B = R->getValueAsOptionalDef(BaseFieldName))
260*1db9f3b2SDimitry Andric       Tree.insert(std::make_pair(B, R));
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric 
263*1db9f3b2SDimitry Andric   for (auto *DeclContext : DeclContextsVector) {
264*1db9f3b2SDimitry Andric     printDeclContext(Tree, DeclContext, OS);
265*1db9f3b2SDimitry Andric   }
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   OS << "#undef DECL_CONTEXT\n";
2680b57cec5SDimitry Andric }
269