ClangTypeNodesEmitter.cpp revision 353942
1353942Sdim//=== ClangTypeNodesEmitter.cpp - Generate type node tables -----*- C++ -*-===//
2353942Sdim//
3353942Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353942Sdim// See https://llvm.org/LICENSE.txt for license information.
5353942Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353942Sdim//
7353942Sdim//===----------------------------------------------------------------------===//
8353942Sdim//
9353942Sdim// This tblgen backend emits the node table (the .def file) for Clang
10353942Sdim// type nodes.
11353942Sdim//
12353942Sdim// This file defines the AST type info database. Each type node is
13353942Sdim// enumerated by providing its name (e.g., "Builtin" or "Enum") and
14353942Sdim// base class (e.g., "Type" or "TagType"). Depending on where in the
15353942Sdim// abstract syntax tree the type will show up, the enumeration uses
16353942Sdim// one of five different macros:
17353942Sdim//
18353942Sdim//    TYPE(Class, Base) - A type that can show up anywhere in the AST,
19353942Sdim//    and might be dependent, canonical, or non-canonical. All clients
20353942Sdim//    will need to understand these types.
21353942Sdim//
22353942Sdim//    ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
23353942Sdim//    the type hierarchy but has no concrete instances.
24353942Sdim//
25353942Sdim//    NON_CANONICAL_TYPE(Class, Base) - A type that can show up
26353942Sdim//    anywhere in the AST but will never be a part of a canonical
27353942Sdim//    type. Clients that only need to deal with canonical types
28353942Sdim//    (ignoring, e.g., typedefs and other type aliases used for
29353942Sdim//    pretty-printing) can ignore these types.
30353942Sdim//
31353942Sdim//    DEPENDENT_TYPE(Class, Base) - A type that will only show up
32353942Sdim//    within a C++ template that has not been instantiated, e.g., a
33353942Sdim//    type that is always dependent. Clients that do not need to deal
34353942Sdim//    with uninstantiated C++ templates can ignore these types.
35353942Sdim//
36353942Sdim//    NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
37353942Sdim//    is non-canonical unless it is dependent.  Defaults to TYPE because
38353942Sdim//    it is neither reliably dependent nor reliably non-canonical.
39353942Sdim//
40353942Sdim// There is a sixth macro, independent of the others.  Most clients
41353942Sdim// will not need to use it.
42353942Sdim//
43353942Sdim//    LEAF_TYPE(Class) - A type that never has inner types.  Clients
44353942Sdim//    which can operate on such types more efficiently may wish to do so.
45353942Sdim//
46353942Sdim//===----------------------------------------------------------------------===//
47353942Sdim
48353942Sdim#include "llvm/ADT/StringRef.h"
49353942Sdim#include "llvm/TableGen/Error.h"
50353942Sdim#include "llvm/TableGen/Record.h"
51353942Sdim#include "llvm/TableGen/TableGenBackend.h"
52353942Sdim#include <set>
53353942Sdim#include <string>
54353942Sdim#include <vector>
55353942Sdim#include "TableGenBackends.h"
56353942Sdim
57353942Sdimusing namespace llvm;
58353942Sdim
59353942Sdim// These are spellings in the generated output.
60353942Sdim#define TypeMacroName "TYPE"
61353942Sdim#define AbstractTypeMacroName "ABSTRACT_TYPE"
62353942Sdim#define DependentTypeMacroName "DEPENDENT_TYPE"
63353942Sdim#define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE"
64353942Sdim#define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE"
65353942Sdim#define TypeMacroArgs "(Class, Base)"
66353942Sdim#define LastTypeMacroName "LAST_TYPE"
67353942Sdim#define LeafTypeMacroName "LEAF_TYPE"
68353942Sdim
69353942Sdim// These are spellings in the tblgen file.
70353942Sdim// (Type is also used for the spelling of the AST class.)
71353942Sdim#define TypeClassName "Type"
72353942Sdim#define DerivedTypeClassName "DerivedType"
73353942Sdim#define AlwaysDependentClassName "AlwaysDependent"
74353942Sdim#define NeverCanonicalClassName "NeverCanonical"
75353942Sdim#define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
76353942Sdim#define LeafTypeClassName "LeafType"
77353942Sdim#define AbstractFieldName "Abstract"
78353942Sdim#define BaseFieldName "Base"
79353942Sdim
80353942Sdimstatic StringRef getIdForType(Record *type) {
81353942Sdim	// The record name is expected to be the full C++ class name,
82353942Sdim	// including "Type".  Check for that and strip it off.
83353942Sdim	auto fullName = type->getName();
84353942Sdim	if (!fullName.endswith("Type"))
85353942Sdim		PrintFatalError(type->getLoc(), "name of Type node doesn't end in Type");
86353942Sdim	return fullName.drop_back(4);
87353942Sdim}
88353942Sdim
89353942Sdimnamespace {
90353942Sdimclass TypeNodeEmitter {
91353942Sdim	RecordKeeper &Records;
92353942Sdim	raw_ostream &Out;
93353942Sdim	const std::vector<Record*> Types;
94353942Sdim	std::vector<StringRef> MacrosToUndef;
95353942Sdim
96353942Sdimpublic:
97353942Sdim	TypeNodeEmitter(RecordKeeper &records, raw_ostream &out)
98353942Sdim		: Records(records), Out(out),
99353942Sdim			Types(Records.getAllDerivedDefinitions("Type")) {
100353942Sdim	}
101353942Sdim
102353942Sdim	void emit();
103353942Sdim
104353942Sdimprivate:
105353942Sdim	void emitFallbackDefine(StringRef macroName, StringRef fallbackMacroName,
106353942Sdim													StringRef args);
107353942Sdim
108353942Sdim	void emitNodeInvocations();
109353942Sdim	void emitLastNodeInvocation();
110353942Sdim	void emitLeafNodeInvocations();
111353942Sdim
112353942Sdim	void addMacroToUndef(StringRef macroName);
113353942Sdim	void emitUndefs();
114353942Sdim};
115353942Sdim}
116353942Sdim
117353942Sdimvoid TypeNodeEmitter::emit() {
118353942Sdim	if (Types.empty())
119353942Sdim		PrintFatalError("no Type records in input!");
120353942Sdim
121353942Sdim	emitSourceFileHeader("An x-macro database of Clang type nodes", Out);
122353942Sdim
123353942Sdim	// Preamble
124353942Sdim	addMacroToUndef(TypeMacroName);
125353942Sdim	addMacroToUndef(AbstractTypeMacroName);
126353942Sdim	emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs);
127353942Sdim	emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs);
128353942Sdim	emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs);
129353942Sdim	emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName,
130353942Sdim										 TypeMacroArgs);
131353942Sdim
132353942Sdim	// Invocations.
133353942Sdim	emitNodeInvocations();
134353942Sdim	emitLastNodeInvocation();
135353942Sdim	emitLeafNodeInvocations();
136353942Sdim
137353942Sdim	// Postmatter
138353942Sdim	emitUndefs();
139353942Sdim}
140353942Sdim
141353942Sdimvoid TypeNodeEmitter::emitFallbackDefine(StringRef macroName,
142353942Sdim																				 StringRef fallbackMacroName,
143353942Sdim																				 StringRef args) {
144353942Sdim  Out << "#ifndef " << macroName << "\n";
145353942Sdim  Out << "#  define " << macroName << args
146353942Sdim  	  << " " << fallbackMacroName << args << "\n";
147353942Sdim  Out << "#endif\n";
148353942Sdim
149353942Sdim  addMacroToUndef(macroName);
150353942Sdim}
151353942Sdim
152353942Sdimvoid TypeNodeEmitter::emitNodeInvocations() {
153353942Sdim	for (auto type : Types) {
154353942Sdim		// The name with the Type suffix.
155353942Sdim		StringRef id = getIdForType(type);
156353942Sdim
157353942Sdim		// Figure out which macro to use.
158353942Sdim		StringRef macroName;
159353942Sdim		auto setMacroName = [&](StringRef newName) {
160353942Sdim			if (!macroName.empty())
161353942Sdim				PrintFatalError(type->getLoc(),
162353942Sdim												Twine("conflict when computing macro name for "
163353942Sdim															"Type node: trying to use both \"")
164353942Sdim													+ macroName + "\" and \"" + newName + "\"");
165353942Sdim			macroName = newName;
166353942Sdim		};
167353942Sdim		if (type->isSubClassOf(AlwaysDependentClassName))
168353942Sdim			setMacroName(DependentTypeMacroName);
169353942Sdim		if (type->isSubClassOf(NeverCanonicalClassName))
170353942Sdim			setMacroName(NonCanonicalTypeMacroName);
171353942Sdim		if (type->isSubClassOf(NeverCanonicalUnlessDependentClassName))
172353942Sdim			setMacroName(NonCanonicalUnlessDependentTypeMacroName);
173353942Sdim		if (type->getValueAsBit(AbstractFieldName))
174353942Sdim			setMacroName(AbstractTypeMacroName);
175353942Sdim		if (macroName.empty())
176353942Sdim			macroName = TypeMacroName;
177353942Sdim
178353942Sdim		// Compute the base class.
179353942Sdim		StringRef baseName = TypeClassName;
180353942Sdim		if (type->isSubClassOf(DerivedTypeClassName))
181353942Sdim			baseName = type->getValueAsDef(BaseFieldName)->getName();
182353942Sdim
183353942Sdim		// Generate the invocation line.
184353942Sdim		Out << macroName << "(" << id << ", " << baseName << ")\n";
185353942Sdim	}
186353942Sdim}
187353942Sdim
188353942Sdimvoid TypeNodeEmitter::emitLastNodeInvocation() {
189353942Sdim	// We check that this is non-empty earlier.
190353942Sdim	Out << "#ifdef " LastTypeMacroName "\n"
191353942Sdim	       LastTypeMacroName "(" << getIdForType(Types.back()) << ")\n"
192353942Sdim				 "#undef " LastTypeMacroName "\n"
193353942Sdim				 "#endif\n";
194353942Sdim}
195353942Sdim
196353942Sdimvoid TypeNodeEmitter::emitLeafNodeInvocations() {
197353942Sdim	Out << "#ifdef " LeafTypeMacroName "\n";
198353942Sdim
199353942Sdim	for (auto type : Types) {
200353942Sdim		if (!type->isSubClassOf(LeafTypeClassName)) continue;
201353942Sdim		Out << LeafTypeMacroName "(" << getIdForType(type) << ")\n";
202353942Sdim	}
203353942Sdim
204353942Sdim	Out << "#undef " LeafTypeMacroName "\n"
205353942Sdim				 "#endif\n";
206353942Sdim}
207353942Sdim
208353942Sdimvoid TypeNodeEmitter::addMacroToUndef(StringRef macroName) {
209353942Sdim	MacrosToUndef.push_back(macroName);
210353942Sdim}
211353942Sdim
212353942Sdimvoid TypeNodeEmitter::emitUndefs() {
213353942Sdim	for (auto &macroName : MacrosToUndef) {
214353942Sdim		Out << "#undef " << macroName << "\n";
215353942Sdim	}
216353942Sdim}
217353942Sdim
218353942Sdimvoid clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) {
219353942Sdim	TypeNodeEmitter(records, out).emit();
220353942Sdim}
221