1 //===- ClangSyntaxEmitter.cpp - Generate clang Syntax Tree nodes ----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6 // See https://llvm.org/LICENSE.txt for license information. 7 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 // These backends consume the definitions of Syntax Tree nodes. 12 // See clang/include/clang/Tooling/Syntax/{Syntax,Nodes}.td 13 // 14 // The -gen-clang-syntax-node-list backend produces a .inc with macro calls 15 // NODE(Kind, BaseKind) 16 // ABSTRACT_NODE(Type, Base, FirstKind, LastKind) 17 // similar to those for AST nodes such as AST/DeclNodes.inc. 18 // 19 // In future, the class definitions will be produced by additional backends. 20 // 21 //===----------------------------------------------------------------------===// 22 #include "TableGenBackends.h" 23 24 #include <deque> 25 26 #include "llvm/Support/FormatVariadic.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include "llvm/TableGen/Record.h" 29 #include "llvm/TableGen/TableGenBackend.h" 30 31 namespace { 32 33 // The class hierarchy of Node types. 34 // We assemble this in order to be able to define the NodeKind enum in a 35 // stable and useful way, where abstract Node subclasses correspond to ranges. 36 class Hierarchy { 37 public: 38 Hierarchy(const llvm::RecordKeeper &Records) { 39 for (llvm::Record *T : Records.getAllDerivedDefinitions("NodeType")) 40 add(T); 41 for (llvm::Record *Derived : Records.getAllDerivedDefinitions("NodeType")) 42 if (llvm::Record *Base = Derived->getValueAsOptionalDef("base")) 43 link(Derived, Base); 44 for (NodeType &N : AllTypes) 45 llvm::sort(N.Derived, [](const NodeType *L, const NodeType *R) { 46 return L->Record->getName() < R->Record->getName(); 47 }); 48 } 49 50 struct NodeType { 51 const llvm::Record *Record = nullptr; 52 const NodeType *Base = nullptr; 53 std::vector<const NodeType *> Derived; 54 llvm::StringRef name() const { return Record->getName(); } 55 }; 56 57 NodeType &get(llvm::StringRef Name = "Node") { 58 auto NI = ByName.find(Name); 59 assert(NI != ByName.end() && "no such node"); 60 return *NI->second; 61 } 62 63 private: 64 void add(const llvm::Record *R) { 65 AllTypes.emplace_back(); 66 AllTypes.back().Record = R; 67 bool Inserted = ByName.try_emplace(R->getName(), &AllTypes.back()).second; 68 assert(Inserted && "Duplicate node name"); 69 (void)Inserted; 70 } 71 72 void link(const llvm::Record *Derived, const llvm::Record *Base) { 73 auto &CN = get(Derived->getName()), &PN = get(Base->getName()); 74 assert(CN.Base == nullptr && "setting base twice"); 75 PN.Derived.push_back(&CN); 76 CN.Base = &PN; 77 } 78 79 std::deque<NodeType> AllTypes; 80 llvm::DenseMap<llvm::StringRef, NodeType *> ByName; 81 }; 82 83 const Hierarchy::NodeType &firstConcrete(const Hierarchy::NodeType &N) { 84 return N.Derived.empty() ? N : firstConcrete(*N.Derived.front()); 85 } 86 const Hierarchy::NodeType &lastConcrete(const Hierarchy::NodeType &N) { 87 return N.Derived.empty() ? N : lastConcrete(*N.Derived.back()); 88 } 89 90 void emitNodeList(const Hierarchy::NodeType &N, llvm::raw_ostream &OS) { 91 // Don't emit ABSTRACT_NODE for node itself, which has no parent. 92 if (N.Base != nullptr) { 93 if (N.Derived.empty()) 94 OS << llvm::formatv("CONCRETE_NODE({0},{1})\n", N.name(), N.Base->name()); 95 else 96 OS << llvm::formatv("ABSTRACT_NODE({0},{1},{2},{3})\n", N.name(), 97 N.Base->name(), firstConcrete(N).name(), 98 lastConcrete(N).name()); 99 } 100 for (const auto *C : N.Derived) 101 emitNodeList(*C, OS); 102 } 103 104 } // namespace 105 106 void clang::EmitClangSyntaxNodeList(llvm::RecordKeeper &Records, 107 llvm::raw_ostream &OS) { 108 llvm::emitSourceFileHeader("Syntax tree node list", OS); 109 OS << "// Generated from " << Records.getInputFilename() << "\n"; 110 OS << R"cpp( 111 #ifndef NODE 112 #define NODE(Kind, Base) 113 #endif 114 115 #ifndef CONCRETE_NODE 116 #define CONCRETE_NODE(Kind, Base) NODE(Kind, Base) 117 #endif 118 119 #ifndef ABSTRACT_NODE 120 #define ABSTRACT_NODE(Kind, Base, First, Last) NODE(Kind, Base) 121 #endif 122 123 )cpp"; 124 emitNodeList(Hierarchy(Records).get(), OS); 125 OS << R"cpp( 126 #undef NODE 127 #undef CONCRETE_NODE 128 #undef ABSTRACT_NODE 129 )cpp"; 130 } 131