xref: /llvm-project/clang/utils/TableGen/ClangTypeNodesEmitter.cpp (revision 63aa8cf6becbeb4983e3d1a7fa3cd8a7c7147118)
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 &macroName : 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