1 //===-- ClangTypeNodesEmitter.cpp - Generate type node tables -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This tblgen backend emits the node table (the .def file) for Clang
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:
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.
22 // ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
23 // the type hierarchy but has no concrete instances.
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.
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.
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.
40 // There is a sixth macro, independent of the others. Most clients
41 // will not need to use it.
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.
46 //===----------------------------------------------------------------------===//
48 #include "ASTTableGen.h"
49 #include "TableGenBackends.h"
51 #include "llvm/ADT/StringRef.h"
52 #include "llvm/TableGen/Error.h"
53 #include "llvm/TableGen/Record.h"
54 #include "llvm/TableGen/TableGenBackend.h"
58 using namespace clang
;
59 using namespace clang::tblgen
;
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"
71 #define TypeClassName "Type"
74 class TypeNodeEmitter
{
75 const RecordKeeper
&Records
;
77 ArrayRef
<const Record
*> Types
;
78 std::vector
<StringRef
> MacrosToUndef
;
81 TypeNodeEmitter(const RecordKeeper
&records
, raw_ostream
&out
)
82 : Records(records
), Out(out
),
83 Types(Records
.getAllDerivedDefinitions(TypeNodeClassName
)) {}
88 void emitFallbackDefine(StringRef macroName
, StringRef fallbackMacroName
,
91 void emitNodeInvocations();
92 void emitLastNodeInvocation(TypeNode lastType
);
93 void emitLeafNodeInvocations();
95 void addMacroToUndef(StringRef macroName
);
100 void TypeNodeEmitter::emit() {
102 PrintFatalError("no Type records in input!");
104 emitSourceFileHeader("An x-macro database of Clang type nodes", Out
, Records
);
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
,
116 emitNodeInvocations();
117 emitLeafNodeInvocations();
123 void TypeNodeEmitter::emitFallbackDefine(StringRef macroName
,
124 StringRef fallbackMacroName
,
126 Out
<< "#ifndef " << macroName
<< "\n";
127 Out
<< "# define " << macroName
<< args
128 << " " << fallbackMacroName
<< args
<< "\n";
131 addMacroToUndef(macroName
);
134 void TypeNodeEmitter::emitNodeInvocations() {
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.
142 // Figure out which macro to use.
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
+ "\"");
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
;
163 // Generate the invocation line.
164 Out
<< macroName
<< "(" << type
.getId() << ", "
165 << base
.getClassName() << ")\n";
170 emitLastNodeInvocation(lastType
);
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"
181 void TypeNodeEmitter::emitLeafNodeInvocations() {
182 Out
<< "#ifdef " LeafTypeMacroName
"\n";
184 for (TypeNode type
: Types
) {
185 if (!type
.isSubClassOf(LeafTypeClassName
)) continue;
186 Out
<< LeafTypeMacroName
"(" << type
.getId() << ")\n";
189 Out
<< "#undef " LeafTypeMacroName
"\n"
193 void TypeNodeEmitter::addMacroToUndef(StringRef macroName
) {
194 MacrosToUndef
.push_back(macroName
);
197 void TypeNodeEmitter::emitUndefs() {
198 for (auto ¯oName
: MacrosToUndef
) {
199 Out
<< "#undef " << macroName
<< "\n";
203 void clang::EmitClangTypeNodes(const RecordKeeper
&records
, raw_ostream
&out
) {
204 TypeNodeEmitter(records
, out
).emit();