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 ¯oHierarchyName() { 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