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 ¯oName : MacrosToUndef) { 202357095Sdim Out << "#undef " << macroName << "\n"; 203357095Sdim } 204353942Sdim} 205353942Sdim 206353942Sdimvoid clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) { 207357095Sdim TypeNodeEmitter(records, out).emit(); 208353942Sdim} 209