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
48357095Sdim#include "ASTTableGen.h"
49357095Sdim#include "TableGenBackends.h"
50357095Sdim
51353942Sdim#include "llvm/ADT/StringRef.h"
52353942Sdim#include "llvm/TableGen/Error.h"
53353942Sdim#include "llvm/TableGen/Record.h"
54353942Sdim#include "llvm/TableGen/TableGenBackend.h"
55353942Sdim#include <set>
56353942Sdim#include <string>
57353942Sdim#include <vector>
58353942Sdim
59353942Sdimusing namespace llvm;
60357095Sdimusing namespace clang;
61357095Sdimusing namespace clang::tblgen;
62353942Sdim
63353942Sdim// These are spellings in the generated output.
64353942Sdim#define TypeMacroName "TYPE"
65353942Sdim#define AbstractTypeMacroName "ABSTRACT_TYPE"
66353942Sdim#define DependentTypeMacroName "DEPENDENT_TYPE"
67353942Sdim#define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE"
68353942Sdim#define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE"
69353942Sdim#define TypeMacroArgs "(Class, Base)"
70353942Sdim#define LastTypeMacroName "LAST_TYPE"
71353942Sdim#define LeafTypeMacroName "LEAF_TYPE"
72353942Sdim
73353942Sdim#define TypeClassName "Type"
74353942Sdim
75353942Sdimnamespace {
76353942Sdimclass TypeNodeEmitter {
77357095Sdim  RecordKeeper &Records;
78357095Sdim  raw_ostream &Out;
79357095Sdim  const std::vector<Record*> Types;
80357095Sdim  std::vector<StringRef> MacrosToUndef;
81353942Sdim
82353942Sdimpublic:
83357095Sdim  TypeNodeEmitter(RecordKeeper &records, raw_ostream &out)
84357095Sdim    : Records(records), Out(out),
85357095Sdim      Types(Records.getAllDerivedDefinitions(TypeNodeClassName)) {
86357095Sdim  }
87353942Sdim
88357095Sdim  void emit();
89353942Sdim
90353942Sdimprivate:
91357095Sdim  void emitFallbackDefine(StringRef macroName, StringRef fallbackMacroName,
92357095Sdim                          StringRef args);
93353942Sdim
94357095Sdim  void emitNodeInvocations();
95357095Sdim  void emitLastNodeInvocation(TypeNode lastType);
96357095Sdim  void emitLeafNodeInvocations();
97353942Sdim
98357095Sdim  void addMacroToUndef(StringRef macroName);
99357095Sdim  void emitUndefs();
100353942Sdim};
101353942Sdim}
102353942Sdim
103353942Sdimvoid TypeNodeEmitter::emit() {
104357095Sdim  if (Types.empty())
105357095Sdim    PrintFatalError("no Type records in input!");
106353942Sdim
107357095Sdim  emitSourceFileHeader("An x-macro database of Clang type nodes", Out);
108353942Sdim
109357095Sdim  // Preamble
110357095Sdim  addMacroToUndef(TypeMacroName);
111357095Sdim  addMacroToUndef(AbstractTypeMacroName);
112357095Sdim  emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs);
113357095Sdim  emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs);
114357095Sdim  emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs);
115357095Sdim  emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName,
116357095Sdim                     TypeMacroArgs);
117353942Sdim
118357095Sdim  // Invocations.
119357095Sdim  emitNodeInvocations();
120357095Sdim  emitLeafNodeInvocations();
121353942Sdim
122357095Sdim  // Postmatter
123357095Sdim  emitUndefs();
124353942Sdim}
125353942Sdim
126353942Sdimvoid TypeNodeEmitter::emitFallbackDefine(StringRef macroName,
127357095Sdim                                         StringRef fallbackMacroName,
128357095Sdim                                         StringRef args) {
129353942Sdim  Out << "#ifndef " << macroName << "\n";
130353942Sdim  Out << "#  define " << macroName << args
131357095Sdim      << " " << fallbackMacroName << args << "\n";
132353942Sdim  Out << "#endif\n";
133353942Sdim
134353942Sdim  addMacroToUndef(macroName);
135353942Sdim}
136353942Sdim
137353942Sdimvoid TypeNodeEmitter::emitNodeInvocations() {
138357095Sdim  TypeNode lastType;
139353942Sdim
140357095Sdim  visitASTNodeHierarchy<TypeNode>(Records, [&](TypeNode type, TypeNode base) {
141357095Sdim    // If this is the Type node itself, skip it; it can't be handled
142357095Sdim    // uniformly by metaprograms because it doesn't have a base.
143357095Sdim    if (!base) return;
144353942Sdim
145357095Sdim    // Figure out which macro to use.
146357095Sdim    StringRef macroName;
147357095Sdim    auto setMacroName = [&](StringRef newName) {
148357095Sdim      if (!macroName.empty())
149357095Sdim        PrintFatalError(type.getLoc(),
150357095Sdim                        Twine("conflict when computing macro name for "
151357095Sdim                              "Type node: trying to use both \"")
152357095Sdim                          + macroName + "\" and \"" + newName + "\"");
153357095Sdim      macroName = newName;
154357095Sdim    };
155357095Sdim    if (type.isSubClassOf(AlwaysDependentClassName))
156357095Sdim      setMacroName(DependentTypeMacroName);
157357095Sdim    if (type.isSubClassOf(NeverCanonicalClassName))
158357095Sdim      setMacroName(NonCanonicalTypeMacroName);
159357095Sdim    if (type.isSubClassOf(NeverCanonicalUnlessDependentClassName))
160357095Sdim      setMacroName(NonCanonicalUnlessDependentTypeMacroName);
161357095Sdim    if (type.isAbstract())
162357095Sdim      setMacroName(AbstractTypeMacroName);
163357095Sdim    if (macroName.empty())
164357095Sdim      macroName = TypeMacroName;
165353942Sdim
166357095Sdim    // Generate the invocation line.
167357095Sdim    Out << macroName << "(" << type.getId() << ", "
168357095Sdim        << base.getClassName() << ")\n";
169357095Sdim
170357095Sdim    lastType = type;
171357095Sdim  });
172357095Sdim
173357095Sdim  emitLastNodeInvocation(lastType);
174353942Sdim}
175353942Sdim
176357095Sdimvoid TypeNodeEmitter::emitLastNodeInvocation(TypeNode type) {
177357095Sdim  // We check that this is non-empty earlier.
178357095Sdim  Out << "#ifdef " LastTypeMacroName "\n"
179357095Sdim         LastTypeMacroName "(" << type.getId() << ")\n"
180357095Sdim         "#undef " LastTypeMacroName "\n"
181357095Sdim         "#endif\n";
182353942Sdim}
183353942Sdim
184353942Sdimvoid TypeNodeEmitter::emitLeafNodeInvocations() {
185357095Sdim  Out << "#ifdef " LeafTypeMacroName "\n";
186353942Sdim
187357095Sdim  for (TypeNode type : Types) {
188357095Sdim    if (!type.isSubClassOf(LeafTypeClassName)) continue;
189357095Sdim    Out << LeafTypeMacroName "(" << type.getId() << ")\n";
190357095Sdim  }
191353942Sdim
192357095Sdim  Out << "#undef " LeafTypeMacroName "\n"
193357095Sdim         "#endif\n";
194353942Sdim}
195353942Sdim
196353942Sdimvoid TypeNodeEmitter::addMacroToUndef(StringRef macroName) {
197357095Sdim  MacrosToUndef.push_back(macroName);
198353942Sdim}
199353942Sdim
200353942Sdimvoid TypeNodeEmitter::emitUndefs() {
201357095Sdim  for (auto &macroName : MacrosToUndef) {
202357095Sdim    Out << "#undef " << macroName << "\n";
203357095Sdim  }
204353942Sdim}
205353942Sdim
206353942Sdimvoid clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) {
207357095Sdim  TypeNodeEmitter(records, out).emit();
208353942Sdim}
209