1 //=== ClangTypeNodesEmitter.cpp - Generate type node tables -----*- C++ -*-===//
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"
60 using namespace clang
;
61 using namespace clang::tblgen
;
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"
73 #define TypeClassName "Type"
76 class TypeNodeEmitter
{
77 RecordKeeper
&Records
;
79 const std::vector
<Record
*> Types
;
80 std::vector
<StringRef
> MacrosToUndef
;
83 TypeNodeEmitter(RecordKeeper
&records
, raw_ostream
&out
)
84 : Records(records
), Out(out
),
85 Types(Records
.getAllDerivedDefinitions(TypeNodeClassName
)) {
91 void emitFallbackDefine(StringRef macroName
, StringRef fallbackMacroName
,
94 void emitNodeInvocations();
95 void emitLastNodeInvocation(TypeNode lastType
);
96 void emitLeafNodeInvocations();
98 void addMacroToUndef(StringRef macroName
);
103 void TypeNodeEmitter::emit() {
105 PrintFatalError("no Type records in input!");
107 emitSourceFileHeader("An x-macro database of Clang type nodes", Out
, Records
);
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
,
119 emitNodeInvocations();
120 emitLeafNodeInvocations();
126 void TypeNodeEmitter::emitFallbackDefine(StringRef macroName
,
127 StringRef fallbackMacroName
,
129 Out
<< "#ifndef " << macroName
<< "\n";
130 Out
<< "# define " << macroName
<< args
131 << " " << fallbackMacroName
<< args
<< "\n";
134 addMacroToUndef(macroName
);
137 void TypeNodeEmitter::emitNodeInvocations() {
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.
145 // Figure out which macro to use.
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
+ "\"");
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
;
166 // Generate the invocation line.
167 Out
<< macroName
<< "(" << type
.getId() << ", "
168 << base
.getClassName() << ")\n";
173 emitLastNodeInvocation(lastType
);
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"
184 void TypeNodeEmitter::emitLeafNodeInvocations() {
185 Out
<< "#ifdef " LeafTypeMacroName
"\n";
187 for (TypeNode type
: Types
) {
188 if (!type
.isSubClassOf(LeafTypeClassName
)) continue;
189 Out
<< LeafTypeMacroName
"(" << type
.getId() << ")\n";
192 Out
<< "#undef " LeafTypeMacroName
"\n"
196 void TypeNodeEmitter::addMacroToUndef(StringRef macroName
) {
197 MacrosToUndef
.push_back(macroName
);
200 void TypeNodeEmitter::emitUndefs() {
201 for (auto ¯oName
: MacrosToUndef
) {
202 Out
<< "#undef " << macroName
<< "\n";
206 void clang::EmitClangTypeNodes(RecordKeeper
&records
, raw_ostream
&out
) {
207 TypeNodeEmitter(records
, out
).emit();