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(Msg: "no Type records in input!" ); |
106 | |
107 | emitSourceFileHeader(Desc: "An x-macro database of Clang type nodes" , OS&: Out, Record: Records); |
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&: Records, visit: [&](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(ErrorLoc: type.getLoc(), |
150 | Msg: 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(x: 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 | |