123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- //=== ClangTypeNodesEmitter.cpp - Generate type node tables -----*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This tblgen backend emits the node table (the .def file) for Clang
- // type nodes.
- //
- // This file defines the AST type info database. Each type node is
- // enumerated by providing its name (e.g., "Builtin" or "Enum") and
- // base class (e.g., "Type" or "TagType"). Depending on where in the
- // abstract syntax tree the type will show up, the enumeration uses
- // one of five different macros:
- //
- // TYPE(Class, Base) - A type that can show up anywhere in the AST,
- // and might be dependent, canonical, or non-canonical. All clients
- // will need to understand these types.
- //
- // ABSTRACT_TYPE(Class, Base) - An abstract class that shows up in
- // the type hierarchy but has no concrete instances.
- //
- // NON_CANONICAL_TYPE(Class, Base) - A type that can show up
- // anywhere in the AST but will never be a part of a canonical
- // type. Clients that only need to deal with canonical types
- // (ignoring, e.g., typedefs and other type aliases used for
- // pretty-printing) can ignore these types.
- //
- // DEPENDENT_TYPE(Class, Base) - A type that will only show up
- // within a C++ template that has not been instantiated, e.g., a
- // type that is always dependent. Clients that do not need to deal
- // with uninstantiated C++ templates can ignore these types.
- //
- // NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
- // is non-canonical unless it is dependent. Defaults to TYPE because
- // it is neither reliably dependent nor reliably non-canonical.
- //
- // There is a sixth macro, independent of the others. Most clients
- // will not need to use it.
- //
- // LEAF_TYPE(Class) - A type that never has inner types. Clients
- // which can operate on such types more efficiently may wish to do so.
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ADT/StringRef.h"
- #include "llvm/TableGen/Error.h"
- #include "llvm/TableGen/Record.h"
- #include "llvm/TableGen/TableGenBackend.h"
- #include <set>
- #include <string>
- #include <vector>
- #include "TableGenBackends.h"
- using namespace llvm;
- // These are spellings in the generated output.
- #define TypeMacroName "TYPE"
- #define AbstractTypeMacroName "ABSTRACT_TYPE"
- #define DependentTypeMacroName "DEPENDENT_TYPE"
- #define NonCanonicalTypeMacroName "NON_CANONICAL_TYPE"
- #define NonCanonicalUnlessDependentTypeMacroName "NON_CANONICAL_UNLESS_DEPENDENT_TYPE"
- #define TypeMacroArgs "(Class, Base)"
- #define LastTypeMacroName "LAST_TYPE"
- #define LeafTypeMacroName "LEAF_TYPE"
- // These are spellings in the tblgen file.
- // (Type is also used for the spelling of the AST class.)
- #define TypeClassName "Type"
- #define DerivedTypeClassName "DerivedType"
- #define AlwaysDependentClassName "AlwaysDependent"
- #define NeverCanonicalClassName "NeverCanonical"
- #define NeverCanonicalUnlessDependentClassName "NeverCanonicalUnlessDependent"
- #define LeafTypeClassName "LeafType"
- #define AbstractFieldName "Abstract"
- #define BaseFieldName "Base"
- static StringRef getIdForType(Record *type) {
- // The record name is expected to be the full C++ class name,
- // including "Type". Check for that and strip it off.
- auto fullName = type->getName();
- if (!fullName.endswith("Type"))
- PrintFatalError(type->getLoc(), "name of Type node doesn't end in Type");
- return fullName.drop_back(4);
- }
- namespace {
- class TypeNodeEmitter {
- RecordKeeper &Records;
- raw_ostream &Out;
- const std::vector<Record*> Types;
- std::vector<StringRef> MacrosToUndef;
- public:
- TypeNodeEmitter(RecordKeeper &records, raw_ostream &out)
- : Records(records), Out(out),
- Types(Records.getAllDerivedDefinitions("Type")) {
- }
- void emit();
- private:
- void emitFallbackDefine(StringRef macroName, StringRef fallbackMacroName,
- StringRef args);
- void emitNodeInvocations();
- void emitLastNodeInvocation();
- void emitLeafNodeInvocations();
- void addMacroToUndef(StringRef macroName);
- void emitUndefs();
- };
- }
- void TypeNodeEmitter::emit() {
- if (Types.empty())
- PrintFatalError("no Type records in input!");
- emitSourceFileHeader("An x-macro database of Clang type nodes", Out);
- // Preamble
- addMacroToUndef(TypeMacroName);
- addMacroToUndef(AbstractTypeMacroName);
- emitFallbackDefine(AbstractTypeMacroName, TypeMacroName, TypeMacroArgs);
- emitFallbackDefine(NonCanonicalTypeMacroName, TypeMacroName, TypeMacroArgs);
- emitFallbackDefine(DependentTypeMacroName, TypeMacroName, TypeMacroArgs);
- emitFallbackDefine(NonCanonicalUnlessDependentTypeMacroName, TypeMacroName,
- TypeMacroArgs);
- // Invocations.
- emitNodeInvocations();
- emitLastNodeInvocation();
- emitLeafNodeInvocations();
- // Postmatter
- emitUndefs();
- }
- void TypeNodeEmitter::emitFallbackDefine(StringRef macroName,
- StringRef fallbackMacroName,
- StringRef args) {
- Out << "#ifndef " << macroName << "\n";
- Out << "# define " << macroName << args
- << " " << fallbackMacroName << args << "\n";
- Out << "#endif\n";
- addMacroToUndef(macroName);
- }
- void TypeNodeEmitter::emitNodeInvocations() {
- for (auto type : Types) {
- // The name with the Type suffix.
- StringRef id = getIdForType(type);
- // Figure out which macro to use.
- StringRef macroName;
- auto setMacroName = [&](StringRef newName) {
- if (!macroName.empty())
- PrintFatalError(type->getLoc(),
- Twine("conflict when computing macro name for "
- "Type node: trying to use both \"")
- + macroName + "\" and \"" + newName + "\"");
- macroName = newName;
- };
- if (type->isSubClassOf(AlwaysDependentClassName))
- setMacroName(DependentTypeMacroName);
- if (type->isSubClassOf(NeverCanonicalClassName))
- setMacroName(NonCanonicalTypeMacroName);
- if (type->isSubClassOf(NeverCanonicalUnlessDependentClassName))
- setMacroName(NonCanonicalUnlessDependentTypeMacroName);
- if (type->getValueAsBit(AbstractFieldName))
- setMacroName(AbstractTypeMacroName);
- if (macroName.empty())
- macroName = TypeMacroName;
- // Compute the base class.
- StringRef baseName = TypeClassName;
- if (type->isSubClassOf(DerivedTypeClassName))
- baseName = type->getValueAsDef(BaseFieldName)->getName();
- // Generate the invocation line.
- Out << macroName << "(" << id << ", " << baseName << ")\n";
- }
- }
- void TypeNodeEmitter::emitLastNodeInvocation() {
- // We check that this is non-empty earlier.
- Out << "#ifdef " LastTypeMacroName "\n"
- LastTypeMacroName "(" << getIdForType(Types.back()) << ")\n"
- "#undef " LastTypeMacroName "\n"
- "#endif\n";
- }
- void TypeNodeEmitter::emitLeafNodeInvocations() {
- Out << "#ifdef " LeafTypeMacroName "\n";
- for (auto type : Types) {
- if (!type->isSubClassOf(LeafTypeClassName)) continue;
- Out << LeafTypeMacroName "(" << getIdForType(type) << ")\n";
- }
- Out << "#undef " LeafTypeMacroName "\n"
- "#endif\n";
- }
- void TypeNodeEmitter::addMacroToUndef(StringRef macroName) {
- MacrosToUndef.push_back(macroName);
- }
- void TypeNodeEmitter::emitUndefs() {
- for (auto ¯oName : MacrosToUndef) {
- Out << "#undef " << macroName << "\n";
- }
- }
- void clang::EmitClangTypeNodes(RecordKeeper &records, raw_ostream &out) {
- TypeNodeEmitter(records, out).emit();
- }
|