1 //===-- ClangTypeNodesEmitter.cpp - Generate type node tables -------------===// 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 <vector> 56 57 using namespace llvm; 58 using namespace clang; 59 using namespace clang::tblgen; 60 61 // These are spellings in the generated output. 62 #define TypeMacroName "TYPE" 63 #define AbstractTypeMacroName "ABSTRACT_TYPE" 64 #define DependentTypeMacroName "DEPENDENT_TYPE" 65 #define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE" 66 #define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE" 67 #define TypeMacroArgs "(Class, Base)" 68 #define LastTypeMacroName "LAST_TYPE" 69 #define LeafTypeMacroName "LEAF_TYPE" 70 71 #define TypeClassName "Type" 72 73 namespace { 74 class TypeNodeEmitter { 75 const RecordKeeper &Records; 76 raw_ostream &Out; 77 ArrayRef<const Record *> Types; 78 std::vector<StringRef> MacrosToUndef; 79 80 public: 81 TypeNodeEmitter(const RecordKeeper &records, raw_ostream &out) 82 : Records(records), Out(out), 83 Types(Records.getAllDerivedDefinitions(TypeNodeClassName)) {} 84 85 void emit(); 86 87 private: 88 void emitFallbackDefine(StringRef macroName, StringRef fallbackMacroName, 89 StringRef args); 90 91 void emitNodeInvocations(); 92 void emitLastNodeInvocation(TypeNode lastType); 93 void emitLeafNodeInvocations(); 94 95 void addMacroToUndef(StringRef macroName); 96 void emitUndefs(); 97 }; 98 } 99 100 void TypeNodeEmitter::emit() { 101 if (Types.empty()) 102 PrintFatalError("no Type records in input!"); 103 104 emitSourceFileHeader("An x-macro database of Clang type nodes", Out, Records); 105 106 // Preamble 107 addMacroToUndef(TypeMacroName); 108 addMacroToUndef(AbstractTypeMacroName); 109 emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs); 110 emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs); 111 emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs); 112 emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName, 113 TypeMacroArgs); 114 115 // Invocations. 116 emitNodeInvocations(); 117 emitLeafNodeInvocations(); 118 119 // Postmatter 120 emitUndefs(); 121 } 122 123 void TypeNodeEmitter::emitFallbackDefine(StringRef macroName, 124 StringRef fallbackMacroName, 125 StringRef args) { 126 Out << "#ifndef " << macroName << "\n"; 127 Out << "# define " << macroName << args 128 << " " << fallbackMacroName << args << "\n"; 129 Out << "#endif\n"; 130 131 addMacroToUndef(macroName); 132 } 133 134 void TypeNodeEmitter::emitNodeInvocations() { 135 TypeNode lastType; 136 137 visitASTNodeHierarchy<TypeNode>(Records, [&](TypeNode type, TypeNode base) { 138 // If this is the Type node itself, skip it; it can't be handled 139 // uniformly by metaprograms because it doesn't have a base. 140 if (!base) return; 141 142 // Figure out which macro to use. 143 StringRef macroName; 144 auto setMacroName = [&](StringRef newName) { 145 if (!macroName.empty()) 146 PrintFatalError(type.getLoc(), 147 Twine("conflict when computing macro name for " 148 "Type node: trying to use both \"") 149 + macroName + "\" and \"" + newName + "\""); 150 macroName = newName; 151 }; 152 if (type.isSubClassOf(AlwaysDependentClassName)) 153 setMacroName(DependentTypeMacroName); 154 if (type.isSubClassOf(NeverCanonicalClassName)) 155 setMacroName(NonCanonicalTypeMacroName); 156 if (type.isSubClassOf(NeverCanonicalUnlessDependentClassName)) 157 setMacroName(NonCanonicalUnlessDependentTypeMacroName); 158 if (type.isAbstract()) 159 setMacroName(AbstractTypeMacroName); 160 if (macroName.empty()) 161 macroName = TypeMacroName; 162 163 // Generate the invocation line. 164 Out << macroName << "(" << type.getId() << ", " 165 << base.getClassName() << ")\n"; 166 167 lastType = type; 168 }); 169 170 emitLastNodeInvocation(lastType); 171 } 172 173 void TypeNodeEmitter::emitLastNodeInvocation(TypeNode type) { 174 // We check that this is non-empty earlier. 175 Out << "#ifdef " LastTypeMacroName "\n" 176 LastTypeMacroName "(" << type.getId() << ")\n" 177 "#undef " LastTypeMacroName "\n" 178 "#endif\n"; 179 } 180 181 void TypeNodeEmitter::emitLeafNodeInvocations() { 182 Out << "#ifdef " LeafTypeMacroName "\n"; 183 184 for (TypeNode type : Types) { 185 if (!type.isSubClassOf(LeafTypeClassName)) continue; 186 Out << LeafTypeMacroName "(" << type.getId() << ")\n"; 187 } 188 189 Out << "#undef " LeafTypeMacroName "\n" 190 "#endif\n"; 191 } 192 193 void TypeNodeEmitter::addMacroToUndef(StringRef macroName) { 194 MacrosToUndef.push_back(macroName); 195 } 196 197 void TypeNodeEmitter::emitUndefs() { 198 for (auto ¯oName : MacrosToUndef) { 199 Out << "#undef " << macroName << "\n"; 200 } 201 } 202 203 void clang::EmitClangTypeNodes(const RecordKeeper &records, raw_ostream &out) { 204 TypeNodeEmitter(records, out).emit(); 205 } 206