1*0b57cec5SDimitry Andric //=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // These tablegen backends emit Clang AST node tables 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "llvm/TableGen/Record.h" 14*0b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 15*0b57cec5SDimitry Andric #include <cctype> 16*0b57cec5SDimitry Andric #include <map> 17*0b57cec5SDimitry Andric #include <set> 18*0b57cec5SDimitry Andric #include <string> 19*0b57cec5SDimitry Andric using namespace llvm; 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric /// ClangASTNodesEmitter - The top-level class emits .inc files containing 22*0b57cec5SDimitry Andric /// declarations of Clang statements. 23*0b57cec5SDimitry Andric /// 24*0b57cec5SDimitry Andric namespace { 25*0b57cec5SDimitry Andric class ClangASTNodesEmitter { 26*0b57cec5SDimitry Andric // A map from a node to each of its derived nodes. 27*0b57cec5SDimitry Andric typedef std::multimap<Record*, Record*> ChildMap; 28*0b57cec5SDimitry Andric typedef ChildMap::const_iterator ChildIterator; 29*0b57cec5SDimitry Andric 30*0b57cec5SDimitry Andric RecordKeeper &Records; 31*0b57cec5SDimitry Andric Record Root; 32*0b57cec5SDimitry Andric const std::string &BaseSuffix; 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric // Create a macro-ized version of a name 35*0b57cec5SDimitry Andric static std::string macroName(std::string S) { 36*0b57cec5SDimitry Andric for (unsigned i = 0; i < S.size(); ++i) 37*0b57cec5SDimitry Andric S[i] = std::toupper(S[i]); 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric return S; 40*0b57cec5SDimitry Andric } 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric // Return the name to be printed in the base field. Normally this is 43*0b57cec5SDimitry Andric // the record's name plus the base suffix, but if it is the root node and 44*0b57cec5SDimitry Andric // the suffix is non-empty, it's just the suffix. 45*0b57cec5SDimitry Andric std::string baseName(Record &R) { 46*0b57cec5SDimitry Andric if (&R == &Root && !BaseSuffix.empty()) 47*0b57cec5SDimitry Andric return BaseSuffix; 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric return R.getName().str() + BaseSuffix; 50*0b57cec5SDimitry Andric } 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS, 53*0b57cec5SDimitry Andric Record *Base); 54*0b57cec5SDimitry Andric public: 55*0b57cec5SDimitry Andric explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N, 56*0b57cec5SDimitry Andric const std::string &S) 57*0b57cec5SDimitry Andric : Records(R), Root(N, SMLoc(), R), BaseSuffix(S) 58*0b57cec5SDimitry Andric {} 59*0b57cec5SDimitry Andric 60*0b57cec5SDimitry Andric // run - Output the .inc file contents 61*0b57cec5SDimitry Andric void run(raw_ostream &OS); 62*0b57cec5SDimitry Andric }; 63*0b57cec5SDimitry Andric } // end anonymous namespace 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 66*0b57cec5SDimitry Andric // Statement Node Tables (.inc file) generation. 67*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric // Returns the first and last non-abstract subrecords 70*0b57cec5SDimitry Andric // Called recursively to ensure that nodes remain contiguous 71*0b57cec5SDimitry Andric std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode( 72*0b57cec5SDimitry Andric const ChildMap &Tree, 73*0b57cec5SDimitry Andric raw_ostream &OS, 74*0b57cec5SDimitry Andric Record *Base) { 75*0b57cec5SDimitry Andric std::string BaseName = macroName(Base->getName()); 76*0b57cec5SDimitry Andric 77*0b57cec5SDimitry Andric ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base); 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric Record *First = nullptr, *Last = nullptr; 80*0b57cec5SDimitry Andric // This might be the pseudo-node for Stmt; don't assume it has an Abstract 81*0b57cec5SDimitry Andric // bit 82*0b57cec5SDimitry Andric if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract")) 83*0b57cec5SDimitry Andric First = Last = Base; 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric for (; i != e; ++i) { 86*0b57cec5SDimitry Andric Record *R = i->second; 87*0b57cec5SDimitry Andric bool Abstract = R->getValueAsBit("Abstract"); 88*0b57cec5SDimitry Andric std::string NodeName = macroName(R->getName()); 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric OS << "#ifndef " << NodeName << "\n"; 91*0b57cec5SDimitry Andric OS << "# define " << NodeName << "(Type, Base) " 92*0b57cec5SDimitry Andric << BaseName << "(Type, Base)\n"; 93*0b57cec5SDimitry Andric OS << "#endif\n"; 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric if (Abstract) 96*0b57cec5SDimitry Andric OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "(" 97*0b57cec5SDimitry Andric << R->getName() << ", " << baseName(*Base) << "))\n"; 98*0b57cec5SDimitry Andric else 99*0b57cec5SDimitry Andric OS << NodeName << "(" << R->getName() << ", " 100*0b57cec5SDimitry Andric << baseName(*Base) << ")\n"; 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric if (Tree.find(R) != Tree.end()) { 103*0b57cec5SDimitry Andric const std::pair<Record *, Record *> &Result 104*0b57cec5SDimitry Andric = EmitNode(Tree, OS, R); 105*0b57cec5SDimitry Andric if (!First && Result.first) 106*0b57cec5SDimitry Andric First = Result.first; 107*0b57cec5SDimitry Andric if (Result.second) 108*0b57cec5SDimitry Andric Last = Result.second; 109*0b57cec5SDimitry Andric } else { 110*0b57cec5SDimitry Andric if (!Abstract) { 111*0b57cec5SDimitry Andric Last = R; 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric if (!First) 114*0b57cec5SDimitry Andric First = R; 115*0b57cec5SDimitry Andric } 116*0b57cec5SDimitry Andric } 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric OS << "#undef " << NodeName << "\n\n"; 119*0b57cec5SDimitry Andric } 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric if (First) { 122*0b57cec5SDimitry Andric assert (Last && "Got a first node but not a last node for a range!"); 123*0b57cec5SDimitry Andric if (Base == &Root) 124*0b57cec5SDimitry Andric OS << "LAST_" << macroName(Root.getName()) << "_RANGE("; 125*0b57cec5SDimitry Andric else 126*0b57cec5SDimitry Andric OS << macroName(Root.getName()) << "_RANGE("; 127*0b57cec5SDimitry Andric OS << Base->getName() << ", " << First->getName() << ", " 128*0b57cec5SDimitry Andric << Last->getName() << ")\n\n"; 129*0b57cec5SDimitry Andric } 130*0b57cec5SDimitry Andric 131*0b57cec5SDimitry Andric return std::make_pair(First, Last); 132*0b57cec5SDimitry Andric } 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric void ClangASTNodesEmitter::run(raw_ostream &OS) { 135*0b57cec5SDimitry Andric emitSourceFileHeader("List of AST nodes of a particular kind", OS); 136*0b57cec5SDimitry Andric 137*0b57cec5SDimitry Andric // Write the preamble 138*0b57cec5SDimitry Andric OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n"; 139*0b57cec5SDimitry Andric OS << "# define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n"; 140*0b57cec5SDimitry Andric OS << "#endif\n"; 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n"; 143*0b57cec5SDimitry Andric OS << "# define " 144*0b57cec5SDimitry Andric << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n"; 145*0b57cec5SDimitry Andric OS << "#endif\n\n"; 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n"; 148*0b57cec5SDimitry Andric OS << "# define LAST_" 149*0b57cec5SDimitry Andric << macroName(Root.getName()) << "_RANGE(Base, First, Last) " 150*0b57cec5SDimitry Andric << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n"; 151*0b57cec5SDimitry Andric OS << "#endif\n\n"; 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric // Emit statements 154*0b57cec5SDimitry Andric const std::vector<Record*> Stmts 155*0b57cec5SDimitry Andric = Records.getAllDerivedDefinitions(Root.getName()); 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric ChildMap Tree; 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric for (unsigned i = 0, e = Stmts.size(); i != e; ++i) { 160*0b57cec5SDimitry Andric Record *R = Stmts[i]; 161*0b57cec5SDimitry Andric 162*0b57cec5SDimitry Andric if (R->getValue("Base")) 163*0b57cec5SDimitry Andric Tree.insert(std::make_pair(R->getValueAsDef("Base"), R)); 164*0b57cec5SDimitry Andric else 165*0b57cec5SDimitry Andric Tree.insert(std::make_pair(&Root, R)); 166*0b57cec5SDimitry Andric } 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric EmitNode(Tree, OS, &Root); 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric OS << "#undef " << macroName(Root.getName()) << "\n"; 171*0b57cec5SDimitry Andric OS << "#undef " << macroName(Root.getName()) << "_RANGE\n"; 172*0b57cec5SDimitry Andric OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n"; 173*0b57cec5SDimitry Andric OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n"; 174*0b57cec5SDimitry Andric } 175*0b57cec5SDimitry Andric 176*0b57cec5SDimitry Andric namespace clang { 177*0b57cec5SDimitry Andric void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS, 178*0b57cec5SDimitry Andric const std::string &N, const std::string &S) { 179*0b57cec5SDimitry Andric ClangASTNodesEmitter(RK, N, S).run(OS); 180*0b57cec5SDimitry Andric } 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric // Emits and addendum to a .inc file to enumerate the clang declaration 183*0b57cec5SDimitry Andric // contexts. 184*0b57cec5SDimitry Andric void EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) { 185*0b57cec5SDimitry Andric // FIXME: Find a .td file format to allow for this to be represented better. 186*0b57cec5SDimitry Andric 187*0b57cec5SDimitry Andric emitSourceFileHeader("List of AST Decl nodes", OS); 188*0b57cec5SDimitry Andric 189*0b57cec5SDimitry Andric OS << "#ifndef DECL_CONTEXT\n"; 190*0b57cec5SDimitry Andric OS << "# define DECL_CONTEXT(DECL)\n"; 191*0b57cec5SDimitry Andric OS << "#endif\n"; 192*0b57cec5SDimitry Andric 193*0b57cec5SDimitry Andric OS << "#ifndef DECL_CONTEXT_BASE\n"; 194*0b57cec5SDimitry Andric OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n"; 195*0b57cec5SDimitry Andric OS << "#endif\n"; 196*0b57cec5SDimitry Andric 197*0b57cec5SDimitry Andric typedef std::set<Record*> RecordSet; 198*0b57cec5SDimitry Andric typedef std::vector<Record*> RecordVector; 199*0b57cec5SDimitry Andric 200*0b57cec5SDimitry Andric RecordVector DeclContextsVector 201*0b57cec5SDimitry Andric = Records.getAllDerivedDefinitions("DeclContext"); 202*0b57cec5SDimitry Andric RecordVector Decls = Records.getAllDerivedDefinitions("Decl"); 203*0b57cec5SDimitry Andric RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end()); 204*0b57cec5SDimitry Andric 205*0b57cec5SDimitry Andric for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) { 206*0b57cec5SDimitry Andric Record *R = *i; 207*0b57cec5SDimitry Andric 208*0b57cec5SDimitry Andric if (R->getValue("Base")) { 209*0b57cec5SDimitry Andric Record *B = R->getValueAsDef("Base"); 210*0b57cec5SDimitry Andric if (DeclContexts.find(B) != DeclContexts.end()) { 211*0b57cec5SDimitry Andric OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n"; 212*0b57cec5SDimitry Andric DeclContexts.erase(B); 213*0b57cec5SDimitry Andric } 214*0b57cec5SDimitry Andric } 215*0b57cec5SDimitry Andric } 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric // To keep identical order, RecordVector may be used 218*0b57cec5SDimitry Andric // instead of RecordSet. 219*0b57cec5SDimitry Andric for (RecordVector::iterator 220*0b57cec5SDimitry Andric i = DeclContextsVector.begin(), e = DeclContextsVector.end(); 221*0b57cec5SDimitry Andric i != e; ++i) 222*0b57cec5SDimitry Andric if (DeclContexts.find(*i) != DeclContexts.end()) 223*0b57cec5SDimitry Andric OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n"; 224*0b57cec5SDimitry Andric 225*0b57cec5SDimitry Andric OS << "#undef DECL_CONTEXT\n"; 226*0b57cec5SDimitry Andric OS << "#undef DECL_CONTEXT_BASE\n"; 227*0b57cec5SDimitry Andric } 228*0b57cec5SDimitry Andric } // end namespace clang 229