1 //=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // These tablegen backends emit Clang AST node tables 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "ASTTableGen.h" 14 #include "TableGenBackends.h" 15 16 #include "llvm/TableGen/Error.h" 17 #include "llvm/TableGen/Record.h" 18 #include "llvm/TableGen/TableGenBackend.h" 19 #include <cctype> 20 #include <map> 21 #include <set> 22 #include <string> 23 using namespace llvm; 24 using namespace clang; 25 using namespace clang::tblgen; 26 27 /// ClangASTNodesEmitter - The top-level class emits .inc files containing 28 /// declarations of Clang statements. 29 /// 30 namespace { 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; 35 36 RecordKeeper &Records; 37 ASTNode Root; 38 const std::string &NodeClassName; 39 const std::string &BaseSuffix; 40 std::string MacroHierarchyName; 41 ChildMap Tree; 42 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]); 47 48 return S; 49 } 50 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; 56 } 57 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()) 63 return BaseSuffix; 64 65 return node.getName().str() + BaseSuffix; 66 } 67 68 void deriveChildTree(); 69 70 std::pair<ASTNode, ASTNode> EmitNode(raw_ostream& OS, ASTNode Base); 71 public: 72 explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N, 73 const std::string &S) 74 : Records(R), NodeClassName(N), BaseSuffix(S) {} 75 76 // run - Output the .inc file contents 77 void run(raw_ostream &OS); 78 }; 79 } // end anonymous namespace 80 81 //===----------------------------------------------------------------------===// 82 // Statement Node Tables (.inc file) generation. 83 //===----------------------------------------------------------------------===// 84 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, 88 ASTNode Base) { 89 std::string BaseName = macroName(std::string(Base.getName())); 90 91 ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base); 92 bool HasChildren = (i != e); 93 94 ASTNode First, Last; 95 if (!Base.isAbstract()) 96 First = Last = Base; 97 98 for (; i != e; ++i) { 99 ASTNode Child = i->second; 100 bool Abstract = Child.isAbstract(); 101 std::string NodeName = macroName(std::string(Child.getName())); 102 103 OS << "#ifndef " << NodeName << "\n"; 104 OS << "# define " << NodeName << "(Type, Base) " 105 << BaseName << "(Type, Base)\n"; 106 OS << "#endif\n"; 107 108 if (Abstract) OS << "ABSTRACT_" << macroHierarchyName() << "("; 109 OS << NodeName << "(" << Child.getName() << ", " << baseName(Base) << ")"; 110 if (Abstract) OS << ")"; 111 OS << "\n"; 112 113 auto Result = EmitNode(OS, Child); 114 assert(Result.first && Result.second && "node didn't have children?"); 115 116 // Update the range of Base. 117 if (!First) First = Result.first; 118 Last = Result.second; 119 120 OS << "#undef " << NodeName << "\n\n"; 121 } 122 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. 125 if (!First) { 126 PrintFatalError(Base.getLoc(), "abstract node has no children"); 127 } 128 assert(Last && "set First without Last"); 129 130 if (HasChildren) { 131 // Use FOO_RANGE unless this is the last of the ranges, in which case 132 // use LAST_FOO_RANGE. 133 if (Base == Root) 134 OS << "LAST_" << macroHierarchyName() << "_RANGE("; 135 else 136 OS << macroHierarchyName() << "_RANGE("; 137 OS << Base.getName() << ", " << First.getName() << ", " 138 << Last.getName() << ")\n\n"; 139 } 140 141 return std::make_pair(First, Last); 142 } 143 144 void ClangASTNodesEmitter::deriveChildTree() { 145 assert(!Root && "already computed tree"); 146 147 // Emit statements 148 const std::vector<Record*> Stmts 149 = Records.getAllDerivedDefinitions(NodeClassName); 150 151 for (unsigned i = 0, e = Stmts.size(); i != e; ++i) { 152 Record *R = Stmts[i]; 153 154 if (auto B = R->getValueAsOptionalDef(BaseFieldName)) 155 Tree.insert(std::make_pair(B, R)); 156 else if (Root) 157 PrintFatalError(R->getLoc(), 158 Twine("multiple root nodes in \"") + NodeClassName 159 + "\" hierarchy"); 160 else 161 Root = R; 162 } 163 164 if (!Root) 165 PrintFatalError(Twine("didn't find root node in \"") + NodeClassName 166 + "\" hierarchy"); 167 } 168 169 void ClangASTNodesEmitter::run(raw_ostream &OS) { 170 deriveChildTree(); 171 172 emitSourceFileHeader("List of AST nodes of a particular kind", OS); 173 174 // Write the preamble 175 OS << "#ifndef ABSTRACT_" << macroHierarchyName() << "\n"; 176 OS << "# define ABSTRACT_" << macroHierarchyName() << "(Type) Type\n"; 177 OS << "#endif\n"; 178 179 OS << "#ifndef " << macroHierarchyName() << "_RANGE\n"; 180 OS << "# define " 181 << macroHierarchyName() << "_RANGE(Base, First, Last)\n"; 182 OS << "#endif\n\n"; 183 184 OS << "#ifndef LAST_" << macroHierarchyName() << "_RANGE\n"; 185 OS << "# define LAST_" 186 << macroHierarchyName() << "_RANGE(Base, First, Last) " 187 << macroHierarchyName() << "_RANGE(Base, First, Last)\n"; 188 OS << "#endif\n\n"; 189 190 EmitNode(OS, Root); 191 192 OS << "#undef " << macroHierarchyName() << "\n"; 193 OS << "#undef " << macroHierarchyName() << "_RANGE\n"; 194 OS << "#undef LAST_" << macroHierarchyName() << "_RANGE\n"; 195 OS << "#undef ABSTRACT_" << macroHierarchyName() << "\n"; 196 } 197 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); 201 } 202 203 // Emits and addendum to a .inc file to enumerate the clang declaration 204 // contexts. 205 void clang::EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) { 206 // FIXME: Find a .td file format to allow for this to be represented better. 207 208 emitSourceFileHeader("List of AST Decl nodes", OS); 209 210 OS << "#ifndef DECL_CONTEXT\n"; 211 OS << "# define DECL_CONTEXT(DECL)\n"; 212 OS << "#endif\n"; 213 214 OS << "#ifndef DECL_CONTEXT_BASE\n"; 215 OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n"; 216 OS << "#endif\n"; 217 218 typedef std::set<Record*> RecordSet; 219 typedef std::vector<Record*> RecordVector; 220 221 RecordVector DeclContextsVector 222 = Records.getAllDerivedDefinitions(DeclContextNodeClassName); 223 RecordVector Decls = Records.getAllDerivedDefinitions(DeclNodeClassName); 224 RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end()); 225 226 for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) { 227 Record *R = *i; 228 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); 233 } 234 } 235 } 236 237 // To keep identical order, RecordVector may be used 238 // instead of RecordSet. 239 for (RecordVector::iterator 240 i = DeclContextsVector.begin(), e = DeclContextsVector.end(); 241 i != e; ++i) 242 if (DeclContexts.find(*i) != DeclContexts.end()) 243 OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n"; 244 245 OS << "#undef DECL_CONTEXT\n"; 246 OS << "#undef DECL_CONTEXT_BASE\n"; 247 } 248