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("no Type records in input!");
106 
107   emitSourceFileHeader("An x-macro database of Clang type nodes", Out);
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, [&](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(type.getLoc(),
150                         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(macroName);
198 }
199 
200 void TypeNodeEmitter::emitUndefs() {
201   for (auto &macroName : 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