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