]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - utils/TableGen/ClangTypeNodesEmitter.cpp
Vendor import of stripped clang trunk r375505, the last commit before
[FreeBSD/FreeBSD.git] / utils / TableGen / ClangTypeNodesEmitter.cpp
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 "llvm/ADT/StringRef.h"
49 #include "llvm/TableGen/Error.h"
50 #include "llvm/TableGen/Record.h"
51 #include "llvm/TableGen/TableGenBackend.h"
52 #include <set>
53 #include <string>
54 #include <vector>
55 #include "TableGenBackends.h"
56
57 using namespace llvm;
58
59 // These are spellings in the generated output.
60 #define TypeMacroName "TYPE"
61 #define AbstractTypeMacroName "ABSTRACT_TYPE"
62 #define DependentTypeMacroName "DEPENDENT_TYPE"
63 #define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE"
64 #define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE"
65 #define TypeMacroArgs "(Class, Base)"
66 #define LastTypeMacroName "LAST_TYPE"
67 #define LeafTypeMacroName "LEAF_TYPE"
68
69 // These are spellings in the tblgen file.
70 // (Type is also used for the spelling of the AST class.)
71 #define TypeClassName "Type"
72 #define DerivedTypeClassName "DerivedType"
73 #define AlwaysDependentClassName "AlwaysDependent"
74 #define NeverCanonicalClassName "NeverCanonical"
75 #define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
76 #define LeafTypeClassName "LeafType"
77 #define AbstractFieldName "Abstract"
78 #define BaseFieldName "Base"
79
80 static StringRef getIdForType(Record *type) {
81         // The record name is expected to be the full C++ class name,
82         // including "Type".  Check for that and strip it off.
83         auto fullName = type->getName();
84         if (!fullName.endswith("Type"))
85                 PrintFatalError(type->getLoc(), "name of Type node doesn't end in Type");
86         return fullName.drop_back(4);
87 }
88
89 namespace {
90 class TypeNodeEmitter {
91         RecordKeeper &Records;
92         raw_ostream &Out;
93         const std::vector<Record*> Types;
94         std::vector<StringRef> MacrosToUndef;
95
96 public:
97         TypeNodeEmitter(RecordKeeper &records, raw_ostream &out)
98                 : Records(records), Out(out),
99                         Types(Records.getAllDerivedDefinitions("Type")) {
100         }
101
102         void emit();
103
104 private:
105         void emitFallbackDefine(StringRef macroName, StringRef fallbackMacroName,
106                                                                                                         StringRef args);
107
108         void emitNodeInvocations();
109         void emitLastNodeInvocation();
110         void emitLeafNodeInvocations();
111
112         void addMacroToUndef(StringRef macroName);
113         void emitUndefs();
114 };
115 }
116
117 void TypeNodeEmitter::emit() {
118         if (Types.empty())
119                 PrintFatalError("no Type records in input!");
120
121         emitSourceFileHeader("An x-macro database of Clang type nodes", Out);
122
123         // Preamble
124         addMacroToUndef(TypeMacroName);
125         addMacroToUndef(AbstractTypeMacroName);
126         emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs);
127         emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs);
128         emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs);
129         emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName, 
130                                                                                  TypeMacroArgs);
131
132         // Invocations.
133         emitNodeInvocations();
134         emitLastNodeInvocation();
135         emitLeafNodeInvocations();
136
137         // Postmatter
138         emitUndefs();
139 }
140
141 void TypeNodeEmitter::emitFallbackDefine(StringRef macroName,
142                                                                                                                                                                  StringRef fallbackMacroName,
143                                                                                                                                                                  StringRef args) {
144   Out << "#ifndef " << macroName << "\n";
145   Out << "#  define " << macroName << args
146           << " " << fallbackMacroName << args << "\n";
147   Out << "#endif\n";
148
149   addMacroToUndef(macroName);
150 }
151
152 void TypeNodeEmitter::emitNodeInvocations() {
153         for (auto type : Types) {
154                 // The name with the Type suffix.
155                 StringRef id = getIdForType(type);
156
157                 // Figure out which macro to use.
158                 StringRef macroName;
159                 auto setMacroName = [&](StringRef newName) {
160                         if (!macroName.empty())
161                                 PrintFatalError(type->getLoc(),
162                                                                                                 Twine("conflict when computing macro name for "
163                                                                                                                         "Type node: trying to use both \"")
164                                                                                                         + macroName + "\" and \"" + newName + "\"");
165                         macroName = newName;
166                 };
167                 if (type->isSubClassOf(AlwaysDependentClassName))
168                         setMacroName(DependentTypeMacroName);
169                 if (type->isSubClassOf(NeverCanonicalClassName))
170                         setMacroName(NonCanonicalTypeMacroName);
171                 if (type->isSubClassOf(NeverCanonicalUnlessDependentClassName))
172                         setMacroName(NonCanonicalUnlessDependentTypeMacroName);
173                 if (type->getValueAsBit(AbstractFieldName))
174                         setMacroName(AbstractTypeMacroName);
175                 if (macroName.empty())
176                         macroName = TypeMacroName;
177
178                 // Compute the base class.
179                 StringRef baseName = TypeClassName;
180                 if (type->isSubClassOf(DerivedTypeClassName))
181                         baseName = type->getValueAsDef(BaseFieldName)->getName();
182
183                 // Generate the invocation line.
184                 Out << macroName << "(" << id << ", " << baseName << ")\n";
185         }
186 }
187
188 void TypeNodeEmitter::emitLastNodeInvocation() {
189         // We check that this is non-empty earlier.
190         Out << "#ifdef " LastTypeMacroName "\n"
191                LastTypeMacroName "(" << getIdForType(Types.back()) << ")\n"
192                                  "#undef " LastTypeMacroName "\n"
193                                  "#endif\n";
194 }
195
196 void TypeNodeEmitter::emitLeafNodeInvocations() {
197         Out << "#ifdef " LeafTypeMacroName "\n";
198
199         for (auto type : Types) {
200                 if (!type->isSubClassOf(LeafTypeClassName)) continue;
201                 Out << LeafTypeMacroName "(" << getIdForType(type) << ")\n";
202         }
203
204         Out << "#undef " LeafTypeMacroName "\n"
205                                  "#endif\n";
206 }
207
208 void TypeNodeEmitter::addMacroToUndef(StringRef macroName) {
209         MacrosToUndef.push_back(macroName);
210 }
211
212 void TypeNodeEmitter::emitUndefs() {
213         for (auto &macroName : MacrosToUndef) {
214                 Out << "#undef " << macroName << "\n";
215         }
216 }
217
218 void clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) {
219         TypeNodeEmitter(records, out).emit();
220 }