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 "ASTTableGen.h" 49#include "TableGenBackends.h" 50 51#include "llvm/ADT/StringRef.h" 52#include "llvm/TableGen/Error.h" 53#include "llvm/TableGen/Record.h" 54#include "llvm/TableGen/TableGenBackend.h" 55#include <set> 56#include <string> 57#include <vector> 58 59using namespace llvm; 60using namespace clang; 61using namespace clang::tblgen; 62 63// These are spellings in the generated output. 64#define TypeMacroName "TYPE" 65#define AbstractTypeMacroName "ABSTRACT_TYPE" 66#define DependentTypeMacroName "DEPENDENT_TYPE" 67#define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE" 68#define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE" 69#define TypeMacroArgs "(Class, Base)" 70#define LastTypeMacroName "LAST_TYPE" 71#define LeafTypeMacroName "LEAF_TYPE" 72 73#define TypeClassName "Type" 74 75namespace { 76class TypeNodeEmitter { 77 RecordKeeper &Records; 78 raw_ostream &Out; 79 const std::vector<Record*> Types; 80 std::vector<StringRef> MacrosToUndef; 81 82public: 83 TypeNodeEmitter(RecordKeeper &records, raw_ostream &out) 84 : Records(records), Out(out), 85 Types(Records.getAllDerivedDefinitions(TypeNodeClassName)) { 86 } 87 88 void emit(); 89 90private: 91 void emitFallbackDefine(StringRef macroName, StringRef fallbackMacroName, 92 StringRef args); 93 94 void emitNodeInvocations(); 95 void emitLastNodeInvocation(TypeNode lastType); 96 void emitLeafNodeInvocations(); 97 98 void addMacroToUndef(StringRef macroName); 99 void emitUndefs(); 100}; 101} 102 103void TypeNodeEmitter::emit() { 104 if (Types.empty()) 105 PrintFatalError("no Type records in input!"); 106 107 emitSourceFileHeader("An x-macro database of Clang type nodes", Out); 108 109 // Preamble 110 addMacroToUndef(TypeMacroName); 111 addMacroToUndef(AbstractTypeMacroName); 112 emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs); 113 emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs); 114 emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs); 115 emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName, 116 TypeMacroArgs); 117 118 // Invocations. 119 emitNodeInvocations(); 120 emitLeafNodeInvocations(); 121 122 // Postmatter 123 emitUndefs(); 124} 125 126void TypeNodeEmitter::emitFallbackDefine(StringRef macroName, 127 StringRef fallbackMacroName, 128 StringRef args) { 129 Out << "#ifndef " << macroName << "\n"; 130 Out << "# define " << macroName << args 131 << " " << fallbackMacroName << args << "\n"; 132 Out << "#endif\n"; 133 134 addMacroToUndef(macroName); 135} 136 137void TypeNodeEmitter::emitNodeInvocations() { 138 TypeNode lastType; 139 140 visitASTNodeHierarchy<TypeNode>(Records, [&](TypeNode type, TypeNode base) { 141 // If this is the Type node itself, skip it; it can't be handled 142 // uniformly by metaprograms because it doesn't have a base. 143 if (!base) return; 144 145 // Figure out which macro to use. 146 StringRef macroName; 147 auto setMacroName = [&](StringRef newName) { 148 if (!macroName.empty()) 149 PrintFatalError(type.getLoc(), 150 Twine("conflict when computing macro name for " 151 "Type node: trying to use both \"") 152 + macroName + "\" and \"" + newName + "\""); 153 macroName = newName; 154 }; 155 if (type.isSubClassOf(AlwaysDependentClassName)) 156 setMacroName(DependentTypeMacroName); 157 if (type.isSubClassOf(NeverCanonicalClassName)) 158 setMacroName(NonCanonicalTypeMacroName); 159 if (type.isSubClassOf(NeverCanonicalUnlessDependentClassName)) 160 setMacroName(NonCanonicalUnlessDependentTypeMacroName); 161 if (type.isAbstract()) 162 setMacroName(AbstractTypeMacroName); 163 if (macroName.empty()) 164 macroName = TypeMacroName; 165 166 // Generate the invocation line. 167 Out << macroName << "(" << type.getId() << ", " 168 << base.getClassName() << ")\n"; 169 170 lastType = type; 171 }); 172 173 emitLastNodeInvocation(lastType); 174} 175 176void TypeNodeEmitter::emitLastNodeInvocation(TypeNode type) { 177 // We check that this is non-empty earlier. 178 Out << "#ifdef " LastTypeMacroName "\n" 179 LastTypeMacroName "(" << type.getId() << ")\n" 180 "#undef " LastTypeMacroName "\n" 181 "#endif\n"; 182} 183 184void TypeNodeEmitter::emitLeafNodeInvocations() { 185 Out << "#ifdef " LeafTypeMacroName "\n"; 186 187 for (TypeNode type : Types) { 188 if (!type.isSubClassOf(LeafTypeClassName)) continue; 189 Out << LeafTypeMacroName "(" << type.getId() << ")\n"; 190 } 191 192 Out << "#undef " LeafTypeMacroName "\n" 193 "#endif\n"; 194} 195 196void TypeNodeEmitter::addMacroToUndef(StringRef macroName) { 197 MacrosToUndef.push_back(macroName); 198} 199 200void TypeNodeEmitter::emitUndefs() { 201 for (auto ¯oName : MacrosToUndef) { 202 Out << "#undef " << macroName << "\n"; 203 } 204} 205 206void clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) { 207 TypeNodeEmitter(records, out).emit(); 208} 209