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 ¯oName : MacrosToUndef) { 214353942Sdim Out << "#undef " << macroName << "\n"; 215353942Sdim } 216353942Sdim} 217353942Sdim 218353942Sdimvoid clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) { 219353942Sdim TypeNodeEmitter(records, out).emit(); 220353942Sdim} 221