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 }
221