diff --git a/llvm/docs/TableGen/BackEnds.rst b/llvm/docs/TableGen/BackEnds.rst index a93f2ace7880..1a142614f677 100644 --- a/llvm/docs/TableGen/BackEnds.rst +++ b/llvm/docs/TableGen/BackEnds.rst @@ -8,22 +8,30 @@ TableGen BackEnds Introduction ============ -TableGen backends are at the core of TableGen's functionality. The source files -provide the semantics to a generated (in memory) structure, but it's up to the -backend to print this out in a way that is meaningful to the user (normally a -C program including a file or a textual list of warnings, options and error -messages). +TableGen backends are at the core of TableGen's functionality. The source +files provide the classes and records that are parsed and end up as a +collection of record instances, but it's up to the backend to interpret and +print the records in a way that is meaningful to the user (normally a C++ +include file or a textual list of warnings, options, and error messages). -TableGen is used by both LLVM and Clang with very different goals. LLVM uses it -as a way to automate the generation of massive amounts of information regarding -instructions, schedules, cores and architecture features. Some backends generate -output that is consumed by more than one source file, so they need to be created -in a way that is easy to use pre-processor tricks. Some backends can also print -C code structures, so that they can be directly included as-is. +TableGen is used by both LLVM, Clang, and MLIR with very different goals. +LLVM uses it as a way to automate the generation of massive amounts of +information regarding instructions, schedules, cores, and architecture +features. Some backends generate output that is consumed by more than one +source file, so they need to be created in a way that makes it is easy for +preprocessor tricks to be used. Some backends can also print C++ code +structures, so that they can be directly included as-is. Clang, on the other hand, uses it mainly for diagnostic messages (errors, warnings, tips) and attributes, so more on the textual end of the scale. +MLIR uses TableGen to define operations, operation dialects, and operation +traits. + +See the :doc:`TableGen Programmer's Reference <./ProgRef>` for an in-depth +description of TableGen, and :doc:`TableGen Backend Developer's Guide +<./BackGuide>` for a guide to writing a new backend. + LLVM BackEnds ============= @@ -928,17 +936,3 @@ in ``-print-records``. These values are not expected to be needed by backends. The standard ``printable`` field can be used to extract a representation of them in TableGen source syntax if necessary. - -How to write a back-end -======================= - -TODO. - -Until we get a step-by-step HowTo for writing TableGen backends, you can at -least grab the boilerplate (build system, new files, etc.) from Clang's -r173931. - -TODO: How they work, how to write one. This section should not contain details -about any particular backend, except maybe ``-print-enums`` as an example. This -should highlight the APIs in ``TableGen/Record.h``. - diff --git a/llvm/docs/TableGen/BackGuide.rst b/llvm/docs/TableGen/BackGuide.rst new file mode 100644 index 000000000000..4d387e3bdaf9 --- /dev/null +++ b/llvm/docs/TableGen/BackGuide.rst @@ -0,0 +1,787 @@ +=================================== +TableGen Backend Developer's Guide +=================================== + +.. sectnum:: + +.. contents:: + :local: + +Introduction +============ + +The purpose of TableGen is to generate complex output files based on +information from source files that are significantly easier to code than the +output files would be, and also easier to maintain and modify over time. The +information is coded in a declarative style involving classes and records, +which are then processed by TableGen. The internalized records are passed on +to various backends, which extract information from a subset of the records +and generate an output file. These output files are typically ``.inc`` files +for C++, but may be any type of file that the backend developer needs. + +This document is a guide to writing a backend for TableGen. It is not a +complete reference manual, but rather a guide to using the facilities +provided by TableGen for the backends. For a complete reference to the +various data structures and functions involved, see the Doxygen +documentation. + +This document assumes that you have read the :doc:`TableGen Programmer's +Reference <./ProgRef>`, which provides a detailed reference for coding +TableGen source files. This document and the relevant Doxygen pages will be +improved over time. + +Data Structures +=============== + +The following sections describe the data structures that contain the classes +and records that are collected from the TableGen source files by the +TableGen parser. Note that the term *class* refers to an abstract record +class, while the term *record* refers to a concrete record. + +Unless otherwise noted, functions associated with classes are instance +functions. + +``RecordKeeper`` +---------------- + +An instance of the ``RecordKeeper`` class acts as the container for all the +classes and records parsed and collected by TableGen. The ``RecordKeeper`` +instance is passed to the backend when it is invoked by TableGen. This class +is usually abbreviated ``RK``. + +There are two maps in the recordkeeper, one for classes and one for records +(the latter often referred to as *defs*). Each map maps the class or record +name to an instance of the ``Record`` class (see `Record`_), which contains +all the information about that class or record. The ``RecordKeeper`` class +defines a type that must be used to declare these maps if they are requested +directly. + +.. code-block:: text + + using RecordMap = std::map, + std::less<>>; + +In addition to the two maps, the ``RecordKeeper`` instance contains: + +* A map that maps the names of global variables to their values. + Global variables are defined in TableGen files with outer + ``defvar`` statements. + +* A counter for naming anonymous records. + +The ``RecordKeeper`` class provides a few useful functions. + +* Functions to get the complete class and record maps. + +* Functions to get a subset of the records based on their parent classes. + +* Functions to get individual classes, records, and globals. + +A ``RecordKeeper`` instance can be printed to an output stream with the ``<<`` +operator. + +``Record`` +---------- + +Each class or record built by TableGen is represented by an instance of +the ``Record`` class. The ``RecordKeeper`` instance contains one map for the +classes and one for the records. The primary data members of a record are +the record name, the vector of field names and their values, and the vector of +superclasses of the record. + +The record name is stored as a pointer to an ``Init`` (see `Init`_), which +is a class whose instances hold TableGen values (sometimes refered to as +*initializers*). The field names and values are stored in a vector of +``RecordVal`` instances (see `RecordVal`_), each of which contains both the +field name and its value. The superclass vector contains a sequence of +pairs, with each pair including the superclass record and its source +file location. + +In addition to those members, a ``Record`` instance contains: + +* A vector of source file locations that includes the record definition + itself, plus the locations of any multiclasses involved in its definition. + +* For a class record, a vector of the class's template arguments. + +* An instance of ``DefInit`` (see `DefInit`_) corresponding to this record. + +* A unique record ID. + +* A boolean that specifies whether this is a class definition. + +* A boolean that specifies whether this is an anonymous record. + +The ``Record`` class provides many useful functions. + +* Functions to get the record name, fields, source file locations, + template arguments, and unique ID. + +* Functions to get all the record's superclasses or just its direct + superclasses. + +* Functions to get a particular field value by specifying its name in various + forms, and returning its value in various forms + (see `Getting Record Names and Fields`_). + +* Boolean functions to check the various attributes of the record. + +A ``Record`` instance can be printed to an output stream with the ``<<`` +operator. + + +``RecordVal`` +------------- + +Each field of a record is stored in an instance of the ``RecordVal`` class. +The ``Record`` instance includes a vector of these value instances. A +``RecordVal`` instance contains the name of the field, stored in an ``Init`` +instance. It also contains the value of the field, likewise stored in an +``Init``. (A better name for this class might be ``RecordField``.) + +In addition to those primary members, the ``RecordVal`` has other data members. + +* The source file location of the field definition. + +* The type of the field, stored as an instance + of the ``RecTy`` class (see `RecTy`_). + +The ``RecordVal`` class provides some useful functions. + +* Functions to get the name of the field in various forms. + +* A function to get the type of the field. + +* A function to get the value of the field. + +* A function to get the source file location. + +Note that field values are more easily obtained directly from the ``Record`` +instance (see `Record`_). + +A ``RecordVal`` instance can be printed to an output stream with the ``<<`` +operator. + +``RecTy`` +--------- + +The ``RecTy`` class is used to represent the types of field values. It is +the base class for a series of subclasses, one for each of the +available field types. The ``RecTy`` class has one data member that is an +enumerated type specifying the specific type of field value. (A better +name for this class might be ``FieldTy``.) + +The ``RecTy`` class provides a few useful functions. + +* A virtual function to get the type name as a string. + +* A virtual function to check whether all the values of this type can + be converted to another given type. + +* A virtual function to check whether this type is a subtype of + another given type. + +* A function to get the corresponding ``list`` + type for lists with elements of this type. For example, the function + returns the ``list`` type when called with the ``int`` type. + +The subclasses that inherit from ``RecTy`` are +``BitRecTy``, +``BitsRecTy``, +``CodeRecTy``, +``DagRecTy``, +``IntRecTy``, +``ListRecTy``, +``RecordRecTy``, and +``StringRecTy``. +Some of these classes have additional members that +are described in the following subsections. + +*All* of the classes derived from ``RecTy`` provide the ``get()`` function. +It returns an instance of ``Recty`` corresponding to the derived class. +Some of the ``get()`` functions require an argument to +specify which particular variant of the type is desired. These arguments are +described in the following subsections. + +A ``RecTy`` instance can be printed to an output stream with the ``<<`` +operator. + +.. warning:: + It is not specified whether there is a single ``RecTy`` instance of a + particular type or multiple instances. + + +``BitsRecTy`` +~~~~~~~~~~~~~ + +This class includes a data member with the size of the ``bits`` value and a +function to get that size. + +The ``get()`` function takes the length of the sequence, *n*, and returns the +``BitsRecTy`` type corresponding to ``bits<``\ *n*\ ``>``. + +``ListRecTy`` +~~~~~~~~~~~~~ + +This class includes a data member that specifies the type of the list's +elements and a function to get that type. + +The ``get()`` function takes the ``RecTy`` *type* of the list members and +returns the ``ListRecTy`` type corresponding to ``list<``\ *type*\ ``>``. + + +``RecordRecTy`` +~~~~~~~~~~~~~~~ + +This class includes data members that contain the list of parent classes of +this record. It also provides a function to obtain the array of classes and +two functions to get the iterator ``begin()`` and ``end()`` values. The +class defines a type for the return values of the latter two functions. + +.. code-block:: text + + using const_record_iterator = Record * const *; + +The ``get()`` function takes an ``ArrayRef`` of pointers to the ``Record`` +instances of the *direct* superclasses of the record and returns the ``RecordRecTy`` +corresponding to the record inheriting from those superclasses. + +``Init`` +-------- + +The ``Init`` class is used to represent TableGen values. The name derives +from *initialization value*. This class should not be confused with the +``RecordVal`` class, which represents record fields, both their names and +values. The ``Init`` class is the base class for a series of +subclasses, one for each of the available value types. + +The primary data member +of ``Init`` is an enumerated type that represents the specific type of the +value. + +The ``Init`` class provides a few useful functions. + +* A boolean virtual function to determine whether a value is completely + specified; that is, has no uninitialized subvalues. + +* Virtual functions to get the value as a string. + +* Virtual functions to cast the value to other types, implement the bit + range feature of TableGen, and implement the list slice feature. + +The subclasses that inherit directly from ``Init`` are +``UnsetInit`` and ``TypedInit``. + +An ``Init`` instance can be printed to an output stream with the ``<<`` +operator. + +.. warning:: + It is not specified whether two separate initialization values with + the same underlying type and value (e.g., two strings with the value + "Hello") are represented by two ``Init``\ s or share the same ``Init``. + +``UnsetInit`` +~~~~~~~~~~~~~ + +This class, a subclass of ``Init``, represents the unset (uninitialized) +value. The static function ``get()`` can be used to obtain the singleton +``Init`` of this type. + + +``TypedInit`` +~~~~~~~~~~~~~ + +This class, a subclass of ``Init``, acts as the parent class of the classes +that represent specific value types (except for the unset value). These +classes include ``BitInit``, ``BitsInit``, ``CodeInit``, ``DagInit``, +``DefInit``, ``IntInit``, ``ListInit``, and ``StringInit``. (There are +additional derived types used by the TableGen parser.) + +This class includes a data member that specifies the ``RecTy`` type of the +value. It provides a function to get that ``RecTy`` type. + +``BitInit`` +~~~~~~~~~~~ + +The ``BitInit`` class is a subclass of ``TypedInit``. Its instances +represent the possible values of a bit: 0 or 1. It includes a data member +that contains the bit. + +*All* of the classes derived from ``TypedInit`` provide the following functions. + +* A static function named ``get()`` that returns an ``Init`` representing + the specified value(s). In the case of ``BitInit``, ``get(true)`` returns + an instance of ``BitInit`` representing true, while ``get(false)`` returns + an instance + representing false. As noted above, it is not specified whether there + is exactly one or more than one ``BitInit`` representing true (or false). + +* A function named ``GetValue()`` that returns the value of the instance + in a more direct form, in this case as a ``bool``. + +``BitsInit`` +~~~~~~~~~~~~ + +The ``BitsInit`` class is a subclass of ``TypedInit``. Its instances +represent sequences of bits, from high-order to low-order. It includes a +data member with the length of the sequence and a vector of pointers to +``Init`` instances, one per bit. + +The class provides the usual ``get()`` function. It does not provide the +``getValue()`` function. + +The class provides the following additional functions. + +* A function to get the number of bits in the sequence. + +* A function that gets a bit specified by an integer index. + +``CodeInit`` +~~~~~~~~~~~~ + +The ``CodeInit`` class is a subclass of ``TypedInit``. Its instances +represent arbitrary-length strings produced from ``code`` literals in the +TableGen files. It includes a data member that contains a ``StringRef`` of +the value. It also includes a data member specifying the source code +location of the code stirng. + +The class provides the usual ``get()`` and ``getValue()`` functions. The +latter function returns the ``StringRef``. + +The ``getLoc()`` function returns the source code location. + + +``DagInit`` +~~~~~~~~~~~ + +The ``DagInit`` class is a subclass of ``TypedInit``. Its instances +represent the possible direct acyclic graphs (``dag``). + +The class includes a pointer to an ``Init`` for the DAG operator and a +pointer to a ``StringInit`` for the operator name. It includes the count of +DAG operands and the count of operand names. Finally, it includes a vector of +pointers to ``Init`` instances for the operands and another to +``StringInit`` instances for the operand names. +(The DAG operands are also referred to as *arguments*.) + +The class provides two forms of the usual ``get()`` function. It does not +provide the usual ``getValue()`` function. + +The class provides many additional functions: + +* Functions to get the operator in various forms and to get the + operator name in various forms. + +* Functions to determine whether there are any operands and to get the + number of operands. + +* Functions to the get the operands, both individually and together. + +* Functions to determine whether there are any names and to + get the number of names + +* Functions to the get the names, both individually and together. + +* Functions to get the operand iterator ``begin()`` and ``end()`` values. + +* Functions to get the name iterator ``begin()`` and ``end()`` values. + +The class defines two types for the return values of the operand and name +iterators. + +.. code-block:: text + + using const_arg_iterator = SmallVectorImpl::const_iterator; + using const_name_iterator = SmallVectorImpl::const_iterator; + + +``DefInit`` +~~~~~~~~~~~ + +The ``DefInit`` class is a subclass of ``TypedInit``. Its instances +represent the records that were collected by TableGen. It includes a data +member that is a pointer to the record's ``Record`` instance. + +The class provides the usual ``get()`` function. It does not provide +``getValue()``. Instead, it provides ``getDef()``, which returns the +``Record`` instance. + +``IntInit`` +~~~~~~~~~~~ + +The ``IntInit`` class is a subclass of ``TypedInit``. Its instances +represent the possible values of a 64-bit integer. It includes a data member +that contains the integer. + +The class provides the usual ``get()`` and ``getValue()`` functions. The +latter function returns the integer as an ``int64_t``. + +The class also provides a function, ``getBit()``, to obtain a specified bit +of the integer value. + +``ListInit`` +~~~~~~~~~~~~ + +The ``ListInit`` class is a subclass of ``TypedInit``. Its instances +represent lists of elements of some type. It includes a data member with the +length of the list and a vector of pointers to ``Init`` instances, one per +element. + +The class provides the usual ``get()`` and ``getValues()`` functions. The +latter function returns an ``ArrayRef`` of the vector of pointers to ``Init`` +instances. + +The class provides these additional functions. + +* A function to get the element type. + +* Functions to get the length of the vector and to determine whether + it is empty. + +* Functions to get an element specified by an integer index and return + it in various forms. + +* Functions to get the iterator ``begin()`` and ``end()`` values. The + class defines a type for the return type of these two functions. + +.. code-block:: text + + using const_iterator = Init *const *; + + +``StringInit`` +~~~~~~~~~~~~~~ + +The ``StringInit`` class is a subclass of ``TypedInit``. Its instances +represent arbitrary-length strings. It includes a data member +that contains a ``StringRef`` of the value. + +The class provides the usual ``get()`` and ``getValue()`` functions. The +latter function returns the ``StringRef``. + +Creating a New Backend +====================== + +The following steps are required to create a new backend for TableGen. + +#. Invent a name for your backend C++ file, say ``GenAddressModes``. + +#. Write the new backend, using the file ``TableGenBackendSkeleton.cpp`` + as a starting point. + +#. Determine which instance of TableGen requires the new backend. There is + one instance for Clang and another for LLVM. Or you may be building + your own instance. + +#. Modify the selected ``tablegen.cpp`` to include your new backend. + + a. Add the name to the enumerated type ``ActionType``. + + #. Add a keyword to the ``ActionType`` command option using the + ``clEnumValN()`` function. + + #. Add a case to the ``switch`` statement in the *xxx*\ ``TableGenMain()`` + function. It should invoke the "main function" of your backend, which + in this case, according to convention, is named ``EmitAddressModes``. + +5. Add a declaration of your "main function" to the corresponding + ``TableGenBackends.h`` header file. + +#. Add your backend C++ file to the appropriate ``CMakeLists.txt`` file so + that it will be built. + +#. Add your C++ file to the system. + +The Backend Skeleton +==================== + +The file ``TableGenBackendSkeleton.cpp`` provides a skeleton C++ translation +unit for writing a new TableGen backend. Here are a few notes on the file. + +* The list of includes is the minimal list required by most backends. + +* As with all LLVM C++ files, it has a ``using namespace llvm;`` statement. + It also has an anonymous namespace that contains all the file-specific + data structure definitions, along with the class embodying the emitter + data members and functions. Continuing with the ``GenAddressModes`` example, + this class is named ``AddressModesEmitter``. + +* The constructor for the emitter class accepts a ``RecordKeeper`` reference, + typically named ``RK``. The ``RecordKeeper`` reference is saved in a data + member so that records can be obtained from it. This data member is usually + named ``Records``. + +* One function is named ``run``. It is invoked by the backend's "main + function" to collect records and emit the output file. It accepts an instance + of the ``raw_ostream`` class, typically named ``OS``. The output file is + emitted by writing to this stream. + +* The ``run`` function should use the ``emitSourceFileHeader`` helper function + to include a standard header in the emitted file. + +* The only function in the ``llvm`` namespace is the backend "main function." + In this example, it is named ``EmitAddressModes``. It creates an instance + of the ``AddressModesEmitter`` class, passing the ``RecordKeeper`` + instance, then invokes the ``run`` function, passing the ``raw_ostream`` + instance. + +All the examples in the remainder of this document will assume the naming +conventions used in the skeleton file. + +Getting Classes +=============== + +The ``RecordKeeper`` class provides two functions for getting the +``Record`` instances for classes defined in the TableGen files. + +* ``getClasses()`` returns a ``RecordMap`` reference for all the classes. + +* ``getClass(``\ *name*\ ``)`` returns a ``Record`` reference for the named + class. + +If you need to iterate over all the class records: + +.. code-block:: text + + for (auto ClassPair : Records.getClasses()) { + Record *ClassRec = ClassPair.second.get(); + ... + } + +``ClassPair.second`` gets the class's ``unique_ptr``, then ``.get()`` gets the +class ``Record`` itself. + + +Getting Records +=============== + +The ``RecordKeeper`` class provides four functions for getting the +``Record`` instances for concrete records defined in the TableGen files. + +* ``getDefs()`` returns a ``RecordMap`` reference for all the concrete + records. + +* ``getDef(``\ *name*\ ``)`` return a ``Record`` reference for the named + concrete record. + +* ``getAllDerivedDefinitions(``\ *classname*\ ``)`` returns a vector of + ``Record`` references for the concrete records that derive from the + given class. + +* ``getAllDerivedDefinitionsTwo(``\ *classname1*\ ``,`` *classname2*\ ``)`` returns + a vector of ``Record`` references for the concrete records that derive from + *both* of the given classes. [function to come] + +This statement obtains all the records that derive from the ``Attribute`` +class and iterates over them. + +.. code-block:: text + + auto AttrRecords = Records.getAllDerivedDefinitions("Attribute"); + for (Record *AttrRec : AttrRecords) { + ... + } + +Getting Record Names and Fields +=============================== + +As described above (see `Record`_), there are multiple functions that +return the name of a record. One particularly useful one is +``getNameInitAsString()``, which returns the name as a ``std::string``. + +There are also multiple functions that return the fields of a record. To +obtain and iterate over all the fields: + +.. code-block:: text + + for (const RecordVal &Field : SomeRec->getValues()) { + ... + } + +You will recall that ``RecordVal`` is the class whose instances contain +information about the fields in records. + +The ``getValue()`` function returns the ``RecordVal`` instance for a field +specified by name. There are multiple overloaded functions, some taking a +``StringRef`` and others taking a ``const Init *``. Some functions return a +``RecordVal *`` and others return a ``const RecordVal *``. If the field does +not exist, a fatal error message is printed. + +More often than not, you are interested in the value of the field, not all +the information in the ``RecordVal``. There is a large set of functions that +take a field name in some form and return its value. One function, +``getValueInit``, returns the value as an ``Init *``. Another function, +``isValueUnset``, returns a boolean specifying whether the value is unset +(uninitialized). + +Most of the functions return the value in some more useful form. For +example: + +.. code-block:: text + + std::vector RegCosts = + SomeRec->getValueAsListOfInts("RegCosts"); + +The field ``RegCosts`` is assumed to be a list of integers. That list is +returned as a ``std::vector`` of 64-bit integers. If the field is not a list +of integers, a fatal error message is printed. + +Here is a function that returns a field value as a ``Record``, but returns +null if the field does not exist. + +.. code-block:: text + + if (Record *BaseRec = SomeRec->getValueAsOptionalDef(BaseFieldName)) { + ... + } + +The field is assumed to have another record as its value. That record is returned +as a pointer to a ``Record``. If the field does not exist or is unset, the +functions returns null. + +Getting Record Superclasses +=========================== + +The ``Record`` class provides a function to obtain the superclasses of a +record. It is named ``getSuperClasses`` and returns an ``ArrayRef`` of an +array of ``std::pair`` pairs. The superclasses are in post-order: the order +in which the superclasses were visited while copying their fields into the +record. Each pair consists of a pointer to the ``Record`` instance for a +superclass record and an instance of the ``SMRange`` class. The range +indicates the source file locations of the beginning and end of the class +definition. + +This example obtains the superclasses of the ``Prototype`` record and then +iterates over the pairs in the returned array. + +.. code-block:: text + + ArrayRef> + Superclasses = Prototype->getSuperClasses(); + for (const auto &SuperPair : Superclasses) { + ... + } + +The ``Record`` class also provides a function, ``getDirectSuperClasses``, to +append the *direct* superclasses of a record to a given vector of type +``SmallVectorImpl``. + +Emitting Text to the Output Stream +================================== + +The ``run`` function is passed a ``raw_ostream`` to which it prints the +output file. By convention, this stream is saved in the emitter class member +named ``OS``, although some ``run`` functions are simple and just use the +stream without saving it. The output can be produced by writing values +directly to the output stream, or by using the ``std::format()`` or +``llvm::formatv()`` functions. + +.. code-block:: text + + OS << "#ifndef " << NodeName << "\n"; + + OS << format("0x%0*x, ", Digits, Value); + +Instances of the following classes can be printed using the ``<<`` operator: +``RecordKeeper``, +``Record``, +``RecTy``, +``RecordVal``, and +``Init``. + +A constant and two helper functions are provided for producing the output +file. The constant ``MAX_LINE_LEN`` specifies the maximum length of output +lines. The helper function ``printLine`` prints a horizontal line comment. +The helper function ``emitSourceFileHeader`` prints the header comment that +should be included at the top of every output file. + +Printing Error Messages +======================= + +TableGen records are often derived from multiple classes and also often +defined through a sequence of multiclasses. Because of this, it can be +difficult for backends to report clear error messages with accurate source +file locations. To make error reporting easier, five error reporting +functions are provided, each with four overloads. [all combinations to come] + +* ``PrintWarning`` prints a message tagged as a warning. + +* ``PrintError`` prints a message tagged as an error. + +* ``PrintFatalError`` prints a message tagged as an error and then terminates. + +* ``PrintNote`` prints a note. It is often used after one of the previous + functions to provide more information. + +* ``PrintFatalNote`` prints a note and then terminates. + +Each of these five functions is overloaded four times. + +* ``PrintError(const Twine &Msg)``: + Prints the message with no source file location. + +* ``PrintError(ArrayRef ErrorLoc, const Twine &Msg)``: + Prints the message followed by the specified source line, + along with a pointer to the item in error. The array of + source file locations is typically taken from a ``Record`` instance. + +* ``PrintError(const Record *Rec, const Twine &Msg)``: + Prints the message followed by the source line associated with the + specified record (see `Record`_). + +* ``PrintError(const RecordVal *RecVal, const Twine &Msg)``: + Prints the message followed by the source line associated with the + specified record field (see `RecordVal`_). + +Using these functions, the goal is to produce the most specific error report +possible. + +Debugging Tools +=============== + +TableGen provides some tools to aid in debugging backends. + +The ``PrintRecords`` Backend +---------------------------- + +The TableGen command option ``--print-records`` invokes a simple backend +that prints all the classes and records defined in the source files. This is +the default backend option. The output looks like this: + +.. code-block:: text + + ------------- Classes ----------------- + ... + class XEntry { // XBase + string Str = XEntry:str; + bits<8> Val1 = { !cast>(XEntry:val1){7}, ... }; + bit Val3 = 1; + } + ... + ------------- Defs ----------------- + def ATable { // GenericTable + string FilterClass = "AEntry"; + string CppTypeName = "AEntry"; + list Fields = ["Str", "Val1", "Val2"]; + list PrimaryKey = ["Val1", "Val2"]; + string PrimaryKeyName = "lookupATableByValues"; + bit PrimaryKeyEarlyOut = 0; + } + ... + def anonymous_0 { // AEntry + string Str = "Bob"; + bits<8> Val1 = { 0, 0, 0, 0, 0, 1, 0, 1 }; + bits<10> Val2 = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 }; + } + +Classes are shown with their template arguments, parent classes (following +``//``), and fields. Records are shown with their parent classes and +fields. Note that anonymous records are named ``anonymous_0``, +``anonymous_1``, etc. + + + +The ``PrintDetailedRecords`` Backend +------------------------------------ + +[to come] diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst index 7bc70c8f89e6..901aee4a32d8 100644 --- a/llvm/docs/TableGen/ProgRef.rst +++ b/llvm/docs/TableGen/ProgRef.rst @@ -26,9 +26,12 @@ you are looking for a simple overview, check out :doc:`TableGen Overview <./inde An example of a backend is ``RegisterInfo``, which generates the register file information for a particular target machine, for use by the LLVM -target-independent code generator. See :doc:`TableGen Backends <./BackEnds>` for -a description of the LLVM TableGen backends. Here are a few of the things -backends can do. +target-independent code generator. See :doc:`TableGen Backends <./BackEnds>` +for a description of the LLVM TableGen backends, and :doc:`TableGen +Backend Developer's Guide <./BackGuide>` for a guide to writing a new +backend. + +Here are a few of the things backends can do. * Generate the register file information for a particular target machine. diff --git a/llvm/lib/TableGen/CMakeLists.txt b/llvm/lib/TableGen/CMakeLists.txt index 1ece81459520..0a0a56c6285c 100644 --- a/llvm/lib/TableGen/CMakeLists.txt +++ b/llvm/lib/TableGen/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_component_library(LLVMTableGen SetTheory.cpp StringMatcher.cpp TableGenBackend.cpp + TableGenBackendSkeleton.cpp TGLexer.cpp TGParser.cpp diff --git a/llvm/lib/TableGen/TableGenBackendSkeleton.cpp b/llvm/lib/TableGen/TableGenBackendSkeleton.cpp new file mode 100644 index 000000000000..e3885154f091 --- /dev/null +++ b/llvm/lib/TableGen/TableGenBackendSkeleton.cpp @@ -0,0 +1,62 @@ +//===- SkeletonEmitter.cpp - Skeleton TableGen backend -*- 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 Tablegen backend emits ... +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" +#include +#include +#include +#include + +#define DEBUG_TYPE "skeleton-emitter" + +using namespace llvm; + +namespace { + +// Any helper data structures can be defined here. Some backends use +// structs to collect information from the records. + +class SkeletonEmitter { +private: + RecordKeeper &Records; + +public: + SkeletonEmitter(RecordKeeper &RK) : Records(RK) {} + + void run(raw_ostream &OS); +}; // End emitter class. + +} // End anonymous namespace. + +void SkeletonEmitter::run(raw_ostream &OS) { + emitSourceFileHeader("Skeleton data structures", OS); +} + +namespace llvm { + +// The only thing that should be in the llvm namespace is the +// emitter entry point function. + +void EmitSkeleton(RecordKeeper &RK, raw_ostream &OS) { + // Instantiate the emitter class and invoke run(). + SkeletonEmitter(RK).run(OS); +} + +} // End llvm namespace. diff --git a/mlir/docs/OpDefinitions.md b/mlir/docs/OpDefinitions.md index 28af8fe2c33f..7c5058e04a9b 100644 --- a/mlir/docs/OpDefinitions.md +++ b/mlir/docs/OpDefinitions.md @@ -57,8 +57,7 @@ including but not limited to: We use TableGen as the language for specifying operation information. TableGen itself just provides syntax for writing records; the syntax and constructs allowed in a TableGen file (typically with filename suffix `.td`) can be found -[here][TableGenIntro]. The formal language specification can be found -[here][TableGenRef]. _Roughly_ speaking, +[here][TableGenProgRef]. * TableGen `class` is similar to C++ class; it can be templated and subclassed. @@ -72,7 +71,7 @@ allowed in a TableGen file (typically with filename suffix `.td`) can be found be anything, including `dag` itself. We can have names attached to both the operator and the arguments like `(MyOp:$op_name MyArg:$arg_name)`. -Please see the [language introduction][TableGenIntro] to learn about all the +Please see the [language reference][TableGenProgRef] to learn about all the types and expressions supported by TableGen. ## Operation Definition @@ -1508,8 +1507,7 @@ requirements that were desirable: TODO: document expectation if the dependent op's definition changes. [TableGen]: https://llvm.org/docs/TableGen/index.html -[TableGenIntro]: https://llvm.org/docs/TableGen/LangIntro.html -[TableGenRef]: https://llvm.org/docs/TableGen/LangRef.html +[TableGenProgRef]: https://llvm.org/docs/TableGen/ProgRef.html [TableGenBackend]: https://llvm.org/docs/TableGen/BackEnds.html#introduction [OpBase]: https://github.com/llvm/llvm-project/blob/master/mlir/include/mlir/IR/OpBase.td [OpDefinitionsGen]: https://github.com/llvm/llvm-project/blob/master/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp diff --git a/mlir/docs/Tutorials/QuickstartRewrites.md b/mlir/docs/Tutorials/QuickstartRewrites.md index ac33aee3c8fc..fbc2406a0f31 100644 --- a/mlir/docs/Tutorials/QuickstartRewrites.md +++ b/mlir/docs/Tutorials/QuickstartRewrites.md @@ -16,7 +16,7 @@ table-driven manner. ## Adding operation An operation in MLIR is specified using a definition in -[TableGen](https://llvm.org/docs/TableGen/LangIntro.html) file. TableGen is a +[TableGen](https://llvm.org/docs/TableGen/index.html) file. TableGen is a modeling tool to specify the ops and the C++ code to interact with these operations are generated from. To define an operation one needs to specify: