1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
| //=== ClangTypeNodesEmitter.cpp - Generate type node tables -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This tblgen backend emits the node table (the .def file) for Clang
// type nodes.
//
// This file defines the AST type info database. Each type node is
// enumerated by providing its name (e.g., "Builtin" or "Enum") and
// base class (e.g., "Type" or "TagType"). Depending on where in the
// abstract syntax tree the type will show up, the enumeration uses
// one of five different macros:
//
// TYPE(Class, Base) - A type that can show up anywhere in the AST,
// and might be dependent, canonical, or non-canonical. All clients
// will need to understand these types.
//
// ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
// the type hierarchy but has no concrete instances.
//
// NON_CANONICAL_TYPE(Class, Base) - A type that can show up
// anywhere in the AST but will never be a part of a canonical
// type. Clients that only need to deal with canonical types
// (ignoring, e.g., typedefs and other type aliases used for
// pretty-printing) can ignore these types.
//
// DEPENDENT_TYPE(Class, Base) - A type that will only show up
// within a C++ template that has not been instantiated, e.g., a
// type that is always dependent. Clients that do not need to deal
// with uninstantiated C++ templates can ignore these types.
//
// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
// is non-canonical unless it is dependent. Defaults to TYPE because
// it is neither reliably dependent nor reliably non-canonical.
//
// There is a sixth macro, independent of the others. Most clients
// will not need to use it.
//
// LEAF_TYPE(Class) - A type that never has inner types. Clients
// which can operate on such types more efficiently may wish to do so.
//
//===----------------------------------------------------------------------===//
#include "ClangASTEmitters.h"
#include "TableGenBackends.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <set>
#include <string>
#include <vector>
using namespace llvm;
// These are spellings in the generated output.
#define TypeMacroName "TYPE"
#define AbstractTypeMacroName "ABSTRACT_TYPE"
#define DependentTypeMacroName "DEPENDENT_TYPE"
#define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE"
#define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE"
#define TypeMacroArgs "(Class, Base)"
#define LastTypeMacroName "LAST_TYPE"
#define LeafTypeMacroName "LEAF_TYPE"
#define TypeClassName "Type"
static StringRef getIdForType(Record *type) {
// The record name is expected to be the full C++ class name,
// including "Type". Check for that and strip it off.
auto fullName = type->getName();
if (!fullName.endswith("Type"))
PrintFatalError(type->getLoc(), "name of Type node doesn't end in Type");
return fullName.drop_back(4);
}
namespace {
class TypeNodeEmitter {
RecordKeeper &Records;
raw_ostream &Out;
const std::vector<Record*> Types;
std::vector<StringRef> MacrosToUndef;
public:
TypeNodeEmitter(RecordKeeper &records, raw_ostream &out)
: Records(records), Out(out),
Types(Records.getAllDerivedDefinitions(TypeNodeClassName)) {
}
void emit();
private:
void emitFallbackDefine(StringRef macroName, StringRef fallbackMacroName,
StringRef args);
void emitNodeInvocations();
void emitLastNodeInvocation();
void emitLeafNodeInvocations();
void addMacroToUndef(StringRef macroName);
void emitUndefs();
};
}
void TypeNodeEmitter::emit() {
if (Types.empty())
PrintFatalError("no Type records in input!");
emitSourceFileHeader("An x-macro database of Clang type nodes", Out);
// Preamble
addMacroToUndef(TypeMacroName);
addMacroToUndef(AbstractTypeMacroName);
emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs);
emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs);
emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs);
emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName,
TypeMacroArgs);
// Invocations.
emitNodeInvocations();
emitLastNodeInvocation();
emitLeafNodeInvocations();
// Postmatter
emitUndefs();
}
void TypeNodeEmitter::emitFallbackDefine(StringRef macroName,
StringRef fallbackMacroName,
StringRef args) {
Out << "#ifndef " << macroName << "\n";
Out << "# define " << macroName << args
<< " " << fallbackMacroName << args << "\n";
Out << "#endif\n";
addMacroToUndef(macroName);
}
void TypeNodeEmitter::emitNodeInvocations() {
for (auto type : Types) {
// The name without the Type suffix.
StringRef id = getIdForType(type);
// If this is the Type node itself, skip it.
if (id.empty()) continue;
// Figure out which macro to use.
StringRef macroName;
auto setMacroName = [&](StringRef newName) {
if (!macroName.empty())
PrintFatalError(type->getLoc(),
Twine("conflict when computing macro name for "
"Type node: trying to use both \"")
+ macroName + "\" and \"" + newName + "\"");
macroName = newName;
};
if (type->isSubClassOf(AlwaysDependentClassName))
setMacroName(DependentTypeMacroName);
if (type->isSubClassOf(NeverCanonicalClassName))
setMacroName(NonCanonicalTypeMacroName);
if (type->isSubClassOf(NeverCanonicalUnlessDependentClassName))
setMacroName(NonCanonicalUnlessDependentTypeMacroName);
if (type->getValueAsBit(AbstractFieldName))
setMacroName(AbstractTypeMacroName);
if (macroName.empty())
macroName = TypeMacroName;
// Compute the base class.
StringRef baseName = TypeClassName;
if (auto base = type->getValueAsOptionalDef(BaseFieldName))
baseName = base->getName();
// Generate the invocation line.
Out << macroName << "(" << id << ", " << baseName << ")\n";
}
}
void TypeNodeEmitter::emitLastNodeInvocation() {
// We check that this is non-empty earlier.
Out << "#ifdef " LastTypeMacroName "\n"
LastTypeMacroName "(" << getIdForType(Types.back()) << ")\n"
"#undef " LastTypeMacroName "\n"
"#endif\n";
}
void TypeNodeEmitter::emitLeafNodeInvocations() {
Out << "#ifdef " LeafTypeMacroName "\n";
for (auto type : Types) {
if (!type->isSubClassOf(LeafTypeClassName)) continue;
Out << LeafTypeMacroName "(" << getIdForType(type) << ")\n";
}
Out << "#undef " LeafTypeMacroName "\n"
"#endif\n";
}
void TypeNodeEmitter::addMacroToUndef(StringRef macroName) {
MacrosToUndef.push_back(macroName);
}
void TypeNodeEmitter::emitUndefs() {
for (auto ¯oName : MacrosToUndef) {
Out << "#undef " << macroName << "\n";
}
}
void clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) {
TypeNodeEmitter(records, out).emit();
}
|