1 //=== ClangTypeNodesEmitter.cpp - Generate type 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 // This tblgen backend emits the node table (the .def file) for Clang 10 // type nodes. 11 // 12 // This file defines the AST type info database. Each type node is 13 // enumerated by providing its name (e.g., "Builtin" or "Enum") and 14 // base class (e.g., "Type" or "TagType"). Depending on where in the 15 // abstract syntax tree the type will show up, the enumeration uses 16 // one of five different macros: 17 // 18 // TYPE(Class, Base) - A type that can show up anywhere in the AST, 19 // and might be dependent, canonical, or non-canonical. All clients 20 // will need to understand these types. 21 // 22 // ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in 23 // the type hierarchy but has no concrete instances. 24 // 25 // NON_CANONICAL_TYPE(Class, Base) - A type that can show up 26 // anywhere in the AST but will never be a part of a canonical 27 // type. Clients that only need to deal with canonical types 28 // (ignoring, e.g., typedefs and other type aliases used for 29 // pretty-printing) can ignore these types. 30 // 31 // DEPENDENT_TYPE(Class, Base) - A type that will only show up 32 // within a C++ template that has not been instantiated, e.g., a 33 // type that is always dependent. Clients that do not need to deal 34 // with uninstantiated C++ templates can ignore these types. 35 // 36 // NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that 37 // is non-canonical unless it is dependent. Defaults to TYPE because 38 // it is neither reliably dependent nor reliably non-canonical. 39 // 40 // There is a sixth macro, independent of the others. Most clients 41 // will not need to use it. 42 // 43 // LEAF_TYPE(Class) - A type that never has inner types. Clients 44 // which can operate on such types more efficiently may wish to do so. 45 // 46 //===----------------------------------------------------------------------===// 47 48 #include "ASTTableGen.h" 49 #include "TableGenBackends.h" 50 51 #include "llvm/ADT/StringRef.h" 52 #include "llvm/TableGen/Error.h" 53 #include "llvm/TableGen/Record.h" 54 #include "llvm/TableGen/TableGenBackend.h" 55 #include <set> 56 #include <string> 57 #include <vector> 58 59 using namespace llvm; 60 using namespace clang; 61 using namespace clang::tblgen; 62 63 // These are spellings in the generated output. 64 #define TypeMacroName "TYPE" 65 #define AbstractTypeMacroName "ABSTRACT_TYPE" 66 #define DependentTypeMacroName "DEPENDENT_TYPE" 67 #define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE" 68 #define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE" 69 #define TypeMacroArgs "(Class, Base)" 70 #define LastTypeMacroName "LAST_TYPE" 71 #define LeafTypeMacroName "LEAF_TYPE" 72 73 #define TypeClassName "Type" 74 75 namespace { 76 class TypeNodeEmitter { 77 RecordKeeper &Records; 78 raw_ostream &Out; 79 const std::vector<Record*> Types; 80 std::vector<StringRef> MacrosToUndef; 81 82 public: 83 TypeNodeEmitter(RecordKeeper &records, raw_ostream &out) 84 : Records(records), Out(out), 85 Types(Records.getAllDerivedDefinitions(TypeNodeClassName)) { 86 } 87 88 void emit(); 89 90 private: 91 void emitFallbackDefine(StringRef macroName, StringRef fallbackMacroName, 92 StringRef args); 93 94 void emitNodeInvocations(); 95 void emitLastNodeInvocation(TypeNode lastType); 96 void emitLeafNodeInvocations(); 97 98 void addMacroToUndef(StringRef macroName); 99 void emitUndefs(); 100 }; 101 } 102 103 void TypeNodeEmitter::emit() { 104 if (Types.empty()) 105 PrintFatalError("no Type records in input!"); 106 107 emitSourceFileHeader("An x-macro database of Clang type nodes", Out); 108 109 // Preamble 110 addMacroToUndef(TypeMacroName); 111 addMacroToUndef(AbstractTypeMacroName); 112 emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs); 113 emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs); 114 emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs); 115 emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName, 116 TypeMacroArgs); 117 118 // Invocations. 119 emitNodeInvocations(); 120 emitLeafNodeInvocations(); 121 122 // Postmatter 123 emitUndefs(); 124 } 125 126 void TypeNodeEmitter::emitFallbackDefine(StringRef macroName, 127 StringRef fallbackMacroName, 128 StringRef args) { 129 Out << "#ifndef " << macroName << "\n"; 130 Out << "# define " << macroName << args 131 << " " << fallbackMacroName << args << "\n"; 132 Out << "#endif\n"; 133 134 addMacroToUndef(macroName); 135 } 136 137 void TypeNodeEmitter::emitNodeInvocations() { 138 TypeNode lastType; 139 140 visitASTNodeHierarchy<TypeNode>(Records, [&](TypeNode type, TypeNode base) { 141 // If this is the Type node itself, skip it; it can't be handled 142 // uniformly by metaprograms because it doesn't have a base. 143 if (!base) return; 144 145 // Figure out which macro to use. 146 StringRef macroName; 147 auto setMacroName = [&](StringRef newName) { 148 if (!macroName.empty()) 149 PrintFatalError(type.getLoc(), 150 Twine("conflict when computing macro name for " 151 "Type node: trying to use both \"") 152 + macroName + "\" and \"" + newName + "\""); 153 macroName = newName; 154 }; 155 if (type.isSubClassOf(AlwaysDependentClassName)) 156 setMacroName(DependentTypeMacroName); 157 if (type.isSubClassOf(NeverCanonicalClassName)) 158 setMacroName(NonCanonicalTypeMacroName); 159 if (type.isSubClassOf(NeverCanonicalUnlessDependentClassName)) 160 setMacroName(NonCanonicalUnlessDependentTypeMacroName); 161 if (type.isAbstract()) 162 setMacroName(AbstractTypeMacroName); 163 if (macroName.empty()) 164 macroName = TypeMacroName; 165 166 // Generate the invocation line. 167 Out << macroName << "(" << type.getId() << ", " 168 << base.getClassName() << ")\n"; 169 170 lastType = type; 171 }); 172 173 emitLastNodeInvocation(lastType); 174 } 175 176 void TypeNodeEmitter::emitLastNodeInvocation(TypeNode type) { 177 // We check that this is non-empty earlier. 178 Out << "#ifdef " LastTypeMacroName "\n" 179 LastTypeMacroName "(" << type.getId() << ")\n" 180 "#undef " LastTypeMacroName "\n" 181 "#endif\n"; 182 } 183 184 void TypeNodeEmitter::emitLeafNodeInvocations() { 185 Out << "#ifdef " LeafTypeMacroName "\n"; 186 187 for (TypeNode type : Types) { 188 if (!type.isSubClassOf(LeafTypeClassName)) continue; 189 Out << LeafTypeMacroName "(" << type.getId() << ")\n"; 190 } 191 192 Out << "#undef " LeafTypeMacroName "\n" 193 "#endif\n"; 194 } 195 196 void TypeNodeEmitter::addMacroToUndef(StringRef macroName) { 197 MacrosToUndef.push_back(macroName); 198 } 199 200 void TypeNodeEmitter::emitUndefs() { 201 for (auto ¯oName : MacrosToUndef) { 202 Out << "#undef " << macroName << "\n"; 203 } 204 } 205 206 void clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) { 207 TypeNodeEmitter(records, out).emit(); 208 } 209