/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/utils/TableGen/ClangTypeNodesEmitter.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 0 | #define TypeMacroName "TYPE" |
65 | 0 | #define AbstractTypeMacroName "ABSTRACT_TYPE" |
66 | 0 | #define DependentTypeMacroName "DEPENDENT_TYPE" |
67 | 0 | #define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE" |
68 | 0 | #define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE" |
69 | 0 | #define TypeMacroArgs "(Class, Base)" |
70 | | #define LastTypeMacroName "LAST_TYPE" |
71 | 0 | #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 | 0 | : Records(records), Out(out), |
85 | 0 | Types(Records.getAllDerivedDefinitions(TypeNodeClassName)) { |
86 | 0 | } |
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 | 0 | void TypeNodeEmitter::emit() { |
104 | 0 | if (Types.empty()) |
105 | 0 | PrintFatalError("no Type records in input!"); |
106 | |
|
107 | 0 | emitSourceFileHeader("An x-macro database of Clang type nodes", Out, Records); |
108 | | |
109 | | // Preamble |
110 | 0 | addMacroToUndef(TypeMacroName); |
111 | 0 | addMacroToUndef(AbstractTypeMacroName); |
112 | 0 | emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs); |
113 | 0 | emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs); |
114 | 0 | emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs); |
115 | 0 | emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName, |
116 | 0 | TypeMacroArgs); |
117 | | |
118 | | // Invocations. |
119 | 0 | emitNodeInvocations(); |
120 | 0 | emitLeafNodeInvocations(); |
121 | | |
122 | | // Postmatter |
123 | 0 | emitUndefs(); |
124 | 0 | } |
125 | | |
126 | | void TypeNodeEmitter::emitFallbackDefine(StringRef macroName, |
127 | | StringRef fallbackMacroName, |
128 | 0 | StringRef args) { |
129 | 0 | Out << "#ifndef " << macroName << "\n"; |
130 | 0 | Out << "# define " << macroName << args |
131 | 0 | << " " << fallbackMacroName << args << "\n"; |
132 | 0 | Out << "#endif\n"; |
133 | |
|
134 | 0 | addMacroToUndef(macroName); |
135 | 0 | } |
136 | | |
137 | 0 | void TypeNodeEmitter::emitNodeInvocations() { |
138 | 0 | TypeNode lastType; |
139 | |
|
140 | 0 | 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 | 0 | if (!base) return; |
144 | | |
145 | | // Figure out which macro to use. |
146 | 0 | StringRef macroName; |
147 | 0 | auto setMacroName = [&](StringRef newName) { |
148 | 0 | if (!macroName.empty()) |
149 | 0 | PrintFatalError(type.getLoc(), |
150 | 0 | Twine("conflict when computing macro name for " |
151 | 0 | "Type node: trying to use both \"") |
152 | 0 | + macroName + "\" and \"" + newName + "\""); |
153 | 0 | macroName = newName; |
154 | 0 | }; |
155 | 0 | if (type.isSubClassOf(AlwaysDependentClassName)) |
156 | 0 | setMacroName(DependentTypeMacroName); |
157 | 0 | if (type.isSubClassOf(NeverCanonicalClassName)) |
158 | 0 | setMacroName(NonCanonicalTypeMacroName); |
159 | 0 | if (type.isSubClassOf(NeverCanonicalUnlessDependentClassName)) |
160 | 0 | setMacroName(NonCanonicalUnlessDependentTypeMacroName); |
161 | 0 | if (type.isAbstract()) |
162 | 0 | setMacroName(AbstractTypeMacroName); |
163 | 0 | if (macroName.empty()) |
164 | 0 | macroName = TypeMacroName; |
165 | | |
166 | | // Generate the invocation line. |
167 | 0 | Out << macroName << "(" << type.getId() << ", " |
168 | 0 | << base.getClassName() << ")\n"; |
169 | |
|
170 | 0 | lastType = type; |
171 | 0 | }); |
172 | |
|
173 | 0 | emitLastNodeInvocation(lastType); |
174 | 0 | } |
175 | | |
176 | 0 | void TypeNodeEmitter::emitLastNodeInvocation(TypeNode type) { |
177 | | // We check that this is non-empty earlier. |
178 | 0 | Out << "#ifdef " LastTypeMacroName "\n" |
179 | 0 | LastTypeMacroName "(" << type.getId() << ")\n" |
180 | 0 | "#undef " LastTypeMacroName "\n" |
181 | 0 | "#endif\n"; |
182 | 0 | } |
183 | | |
184 | 0 | void TypeNodeEmitter::emitLeafNodeInvocations() { |
185 | 0 | Out << "#ifdef " LeafTypeMacroName "\n"; |
186 | |
|
187 | 0 | for (TypeNode type : Types) { |
188 | 0 | if (!type.isSubClassOf(LeafTypeClassName)) continue; |
189 | 0 | Out << LeafTypeMacroName "(" << type.getId() << ")\n"; |
190 | 0 | } |
191 | |
|
192 | 0 | Out << "#undef " LeafTypeMacroName "\n" |
193 | 0 | "#endif\n"; |
194 | 0 | } |
195 | | |
196 | 0 | void TypeNodeEmitter::addMacroToUndef(StringRef macroName) { |
197 | 0 | MacrosToUndef.push_back(macroName); |
198 | 0 | } |
199 | | |
200 | 0 | void TypeNodeEmitter::emitUndefs() { |
201 | 0 | for (auto ¯oName : MacrosToUndef) { |
202 | 0 | Out << "#undef " << macroName << "\n"; |
203 | 0 | } |
204 | 0 | } |
205 | | |
206 | 0 | void clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) { |
207 | 0 | TypeNodeEmitter(records, out).emit(); |
208 | 0 | } |