| ================= |
| TableGen BackEnds |
| ================= |
| |
| .. contents:: |
| :local: |
| |
| Introduction |
| ============ |
| |
| 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, 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 the :doc:`TableGen Backend Developer's Guide |
| <./BackGuide>` for a guide to writing a new backend. |
| |
| LLVM BackEnds |
| ============= |
| |
| .. warning:: |
| This portion is incomplete. Each section below needs three subsections: |
| description of its purpose with a list of users, output generated from |
| generic input, and finally why it needed a new backend (in case there's |
| something similar). |
| |
| Overall, each backend will take the same TableGen file type and transform into |
| similar output for different targets/uses. There is an implicit contract between |
| the TableGen files, the back-ends and their users. |
| |
| For instance, a global contract is that each back-end produces macro-guarded |
| sections. Based on whether the file is included by a header or a source file, |
| or even in which context of each file the include is being used, you have |
| todefine a macro just before including it, to get the right output: |
| |
| .. code-block:: c++ |
| |
| #define GET_REGINFO_TARGET_DESC |
| #include "ARMGenRegisterInfo.inc" |
| |
| And just part of the generated file would be included. This is useful if |
| you need the same information in multiple formats (instantiation, initialization, |
| getter/setter functions, etc) from the same source TableGen file without having |
| to re-compile the TableGen file multiple times. |
| |
| Sometimes, multiple macros might be defined before the same include file to |
| output multiple blocks: |
| |
| .. code-block:: c++ |
| |
| #define GET_REGISTER_MATCHER |
| #define GET_SUBTARGET_FEATURE_NAME |
| #define GET_MATCHER_IMPLEMENTATION |
| #include "ARMGenAsmMatcher.inc" |
| |
| The macros will be undef'd automatically as they're used, in the include file. |
| |
| On all LLVM back-ends, the ``llvm-tblgen`` binary will be executed on the root |
| TableGen file ``<Target>.td``, which should include all others. This guarantees |
| that all information needed is accessible, and that no duplication is needed |
| in the TableGen files. |
| |
| CodeEmitter |
| ----------- |
| |
| **Purpose**: CodeEmitterGen uses the descriptions of instructions and their fields to |
| construct an automated code emitter: a function that, given a MachineInstr, |
| returns the (currently, 32-bit unsigned) value of the instruction. |
| |
| **Output**: C++ code, implementing the target's CodeEmitter |
| class by overriding the virtual functions as ``<Target>CodeEmitter::function()``. |
| |
| **Usage**: Used to include directly at the end of ``<Target>MCCodeEmitter.cpp``. |
| |
| RegisterInfo |
| ------------ |
| |
| **Purpose**: This tablegen backend is responsible for emitting a description of a target |
| register file for a code generator. It uses instances of the Register, |
| RegisterAliases, and RegisterClass classes to gather this information. |
| |
| **Output**: C++ code with enums and structures representing the register mappings, |
| properties, masks, etc. |
| |
| **Usage**: Both on ``<Target>BaseRegisterInfo`` and ``<Target>MCTargetDesc`` (headers |
| and source files) with macros defining in which they are for declaration vs. |
| initialization issues. |
| |
| InstrInfo |
| --------- |
| |
| **Purpose**: This tablegen backend is responsible for emitting a description of the target |
| instruction set for the code generator. (what are the differences from CodeEmitter?) |
| |
| **Output**: C++ code with enums and structures representing the instruction mappings, |
| properties, masks, etc. |
| |
| **Usage**: Both on ``<Target>BaseInstrInfo`` and ``<Target>MCTargetDesc`` (headers |
| and source files) with macros defining in which they are for declaration vs. |
| initialization issues. |
| |
| AsmWriter |
| --------- |
| |
| **Purpose**: Emits an assembly printer for the current target. |
| |
| **Output**: Implementation of ``<Target>InstPrinter::printInstruction()``, among |
| other things. |
| |
| **Usage**: Included directly into ``InstPrinter/<Target>InstPrinter.cpp``. |
| |
| AsmMatcher |
| ---------- |
| |
| **Purpose**: Emits a target specifier matcher for |
| converting parsed assembly operands in the MCInst structures. It also |
| emits a matcher for custom operand parsing. Extensive documentation is |
| written on the ``AsmMatcherEmitter.cpp`` file. |
| |
| **Output**: Assembler parsers' matcher functions, declarations, etc. |
| |
| **Usage**: Used in back-ends' ``AsmParser/<Target>AsmParser.cpp`` for |
| building the AsmParser class. |
| |
| Disassembler |
| ------------ |
| |
| **Purpose**: Contains disassembler table emitters for various |
| architectures. Extensive documentation is written on the |
| ``DisassemblerEmitter.cpp`` file. |
| |
| **Output**: Decoding tables, static decoding functions, etc. |
| |
| **Usage**: Directly included in ``Disassembler/<Target>Disassembler.cpp`` |
| to cater for all default decodings, after all hand-made ones. |
| |
| PseudoLowering |
| -------------- |
| |
| **Purpose**: Generate pseudo instruction lowering. |
| |
| **Output**: Implements ``<Target>AsmPrinter::emitPseudoExpansionLowering()``. |
| |
| **Usage**: Included directly into ``<Target>AsmPrinter.cpp``. |
| |
| CallingConv |
| ----------- |
| |
| **Purpose**: Responsible for emitting descriptions of the calling |
| conventions supported by this target. |
| |
| **Output**: Implement static functions to deal with calling conventions |
| chained by matching styles, returning false on no match. |
| |
| **Usage**: Used in ISelLowering and FastIsel as function pointers to |
| implementation returned by a CC selection function. |
| |
| DAGISel |
| ------- |
| |
| **Purpose**: Generate a DAG instruction selector. |
| |
| **Output**: Creates huge functions for automating DAG selection. |
| |
| **Usage**: Included in ``<Target>ISelDAGToDAG.cpp`` inside the target's |
| implementation of ``SelectionDAGISel``. |
| |
| DFAPacketizer |
| ------------- |
| |
| **Purpose**: This class parses the Schedule.td file and produces an API that |
| can be used to reason about whether an instruction can be added to a packet |
| on a VLIW architecture. The class internally generates a deterministic finite |
| automaton (DFA) that models all possible mappings of machine instructions |
| to functional units as instructions are added to a packet. |
| |
| **Output**: Scheduling tables for GPU back-ends (Hexagon, AMD). |
| |
| **Usage**: Included directly on ``<Target>InstrInfo.cpp``. |
| |
| FastISel |
| -------- |
| |
| **Purpose**: This tablegen backend emits code for use by the "fast" |
| instruction selection algorithm. See the comments at the top of |
| lib/CodeGen/SelectionDAG/FastISel.cpp for background. This file |
| scans through the target's tablegen instruction-info files |
| and extracts instructions with obvious-looking patterns, and it emits |
| code to look up these instructions by type and operator. |
| |
| **Output**: Generates ``Predicate`` and ``FastEmit`` methods. |
| |
| **Usage**: Implements private methods of the targets' implementation |
| of ``FastISel`` class. |
| |
| Subtarget |
| --------- |
| |
| **Purpose**: Generate subtarget enumerations. |
| |
| **Output**: Enums, globals, local tables for sub-target information. |
| |
| **Usage**: Populates ``<Target>Subtarget`` and |
| ``MCTargetDesc/<Target>MCTargetDesc`` files (both headers and source). |
| |
| Intrinsic |
| --------- |
| |
| **Purpose**: Generate (target) intrinsic information. |
| |
| OptParserDefs |
| ------------- |
| |
| **Purpose**: Print enum values for a class. |
| |
| SearchableTables |
| ---------------- |
| |
| **Purpose**: Generate custom searchable tables. |
| |
| **Output**: Enums, global tables, and lookup helper functions. |
| |
| **Usage**: This backend allows generating free-form, target-specific tables |
| from TableGen records. The ARM and AArch64 targets use this backend to generate |
| tables of system registers; the AMDGPU target uses it to generate meta-data |
| about complex image and memory buffer instructions. |
| |
| See `SearchableTables Reference`_ for a detailed description. |
| |
| CTags |
| ----- |
| |
| **Purpose**: This tablegen backend emits an index of definitions in ctags(1) |
| format. A helper script, utils/TableGen/tdtags, provides an easier-to-use |
| interface; run 'tdtags -H' for documentation. |
| |
| X86EVEX2VEX |
| ----------- |
| |
| **Purpose**: This X86 specific tablegen backend emits tables that map EVEX |
| encoded instructions to their VEX encoded identical instruction. |
| |
| Clang BackEnds |
| ============== |
| |
| ClangAttrClasses |
| ---------------- |
| |
| **Purpose**: Creates Attrs.inc, which contains semantic attribute class |
| declarations for any attribute in ``Attr.td`` that has not set ``ASTNode = 0``. |
| This file is included as part of ``Attr.h``. |
| |
| ClangAttrParserStringSwitches |
| ----------------------------- |
| |
| **Purpose**: Creates AttrParserStringSwitches.inc, which contains |
| StringSwitch::Case statements for parser-related string switches. Each switch |
| is given its own macro (such as ``CLANG_ATTR_ARG_CONTEXT_LIST``, or |
| ``CLANG_ATTR_IDENTIFIER_ARG_LIST``), which is expected to be defined before |
| including AttrParserStringSwitches.inc, and undefined after. |
| |
| ClangAttrImpl |
| ------------- |
| |
| **Purpose**: Creates AttrImpl.inc, which contains semantic attribute class |
| definitions for any attribute in ``Attr.td`` that has not set ``ASTNode = 0``. |
| This file is included as part of ``AttrImpl.cpp``. |
| |
| ClangAttrList |
| ------------- |
| |
| **Purpose**: Creates AttrList.inc, which is used when a list of semantic |
| attribute identifiers is required. For instance, ``AttrKinds.h`` includes this |
| file to generate the list of ``attr::Kind`` enumeration values. This list is |
| separated out into multiple categories: attributes, inheritable attributes, and |
| inheritable parameter attributes. This categorization happens automatically |
| based on information in ``Attr.td`` and is used to implement the ``classof`` |
| functionality required for ``dyn_cast`` and similar APIs. |
| |
| ClangAttrPCHRead |
| ---------------- |
| |
| **Purpose**: Creates AttrPCHRead.inc, which is used to deserialize attributes |
| in the ``ASTReader::ReadAttributes`` function. |
| |
| ClangAttrPCHWrite |
| ----------------- |
| |
| **Purpose**: Creates AttrPCHWrite.inc, which is used to serialize attributes in |
| the ``ASTWriter::WriteAttributes`` function. |
| |
| ClangAttrSpellings |
| --------------------- |
| |
| **Purpose**: Creates AttrSpellings.inc, which is used to implement the |
| ``__has_attribute`` feature test macro. |
| |
| ClangAttrSpellingListIndex |
| -------------------------- |
| |
| **Purpose**: Creates AttrSpellingListIndex.inc, which is used to map parsed |
| attribute spellings (including which syntax or scope was used) to an attribute |
| spelling list index. These spelling list index values are internal |
| implementation details exposed via |
| ``AttributeList::getAttributeSpellingListIndex``. |
| |
| ClangAttrVisitor |
| ------------------- |
| |
| **Purpose**: Creates AttrVisitor.inc, which is used when implementing |
| recursive AST visitors. |
| |
| ClangAttrTemplateInstantiate |
| ---------------------------- |
| |
| **Purpose**: Creates AttrTemplateInstantiate.inc, which implements the |
| ``instantiateTemplateAttribute`` function, used when instantiating a template |
| that requires an attribute to be cloned. |
| |
| ClangAttrParsedAttrList |
| ----------------------- |
| |
| **Purpose**: Creates AttrParsedAttrList.inc, which is used to generate the |
| ``AttributeList::Kind`` parsed attribute enumeration. |
| |
| ClangAttrParsedAttrImpl |
| ----------------------- |
| |
| **Purpose**: Creates AttrParsedAttrImpl.inc, which is used by |
| ``AttributeList.cpp`` to implement several functions on the ``AttributeList`` |
| class. This functionality is implemented via the ``AttrInfoMap ParsedAttrInfo`` |
| array, which contains one element per parsed attribute object. |
| |
| ClangAttrParsedAttrKinds |
| ------------------------ |
| |
| **Purpose**: Creates AttrParsedAttrKinds.inc, which is used to implement the |
| ``AttributeList::getKind`` function, mapping a string (and syntax) to a parsed |
| attribute ``AttributeList::Kind`` enumeration. |
| |
| ClangAttrDump |
| ------------- |
| |
| **Purpose**: Creates AttrDump.inc, which dumps information about an attribute. |
| It is used to implement ``ASTDumper::dumpAttr``. |
| |
| ClangDiagsDefs |
| -------------- |
| |
| Generate Clang diagnostics definitions. |
| |
| ClangDiagGroups |
| --------------- |
| |
| Generate Clang diagnostic groups. |
| |
| ClangDiagsIndexName |
| ------------------- |
| |
| Generate Clang diagnostic name index. |
| |
| ClangCommentNodes |
| ----------------- |
| |
| Generate Clang AST comment nodes. |
| |
| ClangDeclNodes |
| -------------- |
| |
| Generate Clang AST declaration nodes. |
| |
| ClangStmtNodes |
| -------------- |
| |
| Generate Clang AST statement nodes. |
| |
| ClangSACheckers |
| --------------- |
| |
| Generate Clang Static Analyzer checkers. |
| |
| ClangCommentHTMLTags |
| -------------------- |
| |
| Generate efficient matchers for HTML tag names that are used in documentation comments. |
| |
| ClangCommentHTMLTagsProperties |
| ------------------------------ |
| |
| Generate efficient matchers for HTML tag properties. |
| |
| ClangCommentHTMLNamedCharacterReferences |
| ---------------------------------------- |
| |
| Generate function to translate named character references to UTF-8 sequences. |
| |
| ClangCommentCommandInfo |
| ----------------------- |
| |
| Generate command properties for commands that are used in documentation comments. |
| |
| ClangCommentCommandList |
| ----------------------- |
| |
| Generate list of commands that are used in documentation comments. |
| |
| ArmNeon |
| ------- |
| |
| Generate arm_neon.h for clang. |
| |
| ArmNeonSema |
| ----------- |
| |
| Generate ARM NEON sema support for clang. |
| |
| ArmNeonTest |
| ----------- |
| |
| Generate ARM NEON tests for clang. |
| |
| AttrDocs |
| -------- |
| |
| **Purpose**: Creates ``AttributeReference.rst`` from ``AttrDocs.td``, and is |
| used for documenting user-facing attributes. |
| |
| General BackEnds |
| ================ |
| |
| Print Records |
| ------------- |
| |
| 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. See the :doc:`TableGen Backend Developer's Guide |
| <./BackGuide>` for more information. |
| |
| Print Detailed Records |
| ---------------------- |
| |
| The TableGen command option ``--print-detailed-records`` invokes a backend |
| that prints all the global variables, classes, and records defined in the |
| source files, with more detail than the default record printer. See the |
| :doc:`TableGen Backend Developer's Guide <./BackGuide>` for more |
| information. |
| |
| JSON Reference |
| -------------- |
| |
| **Purpose**: Output all the values in every ``def``, as a JSON data |
| structure that can be easily parsed by a variety of languages. Useful |
| for writing custom backends without having to modify TableGen itself, |
| or for performing auxiliary analysis on the same TableGen data passed |
| to a built-in backend. |
| |
| **Output**: |
| |
| The root of the output file is a JSON object (i.e. dictionary), |
| containing the following fixed keys: |
| |
| * ``!tablegen_json_version``: a numeric version field that will |
| increase if an incompatible change is ever made to the structure of |
| this data. The format described here corresponds to version 1. |
| |
| * ``!instanceof``: a dictionary whose keys are the class names defined |
| in the TableGen input. For each key, the corresponding value is an |
| array of strings giving the names of ``def`` records that derive |
| from that class. So ``root["!instanceof"]["Instruction"]``, for |
| example, would list the names of all the records deriving from the |
| class ``Instruction``. |
| |
| For each ``def`` record, the root object also has a key for the record |
| name. The corresponding value is a subsidiary object containing the |
| following fixed keys: |
| |
| * ``!superclasses``: an array of strings giving the names of all the |
| classes that this record derives from. |
| |
| * ``!fields``: an array of strings giving the names of all the variables |
| in this record that were defined with the ``field`` keyword. |
| |
| * ``!name``: a string giving the name of the record. This is always |
| identical to the key in the JSON root object corresponding to this |
| record's dictionary. (If the record is anonymous, the name is |
| arbitrary.) |
| |
| * ``!anonymous``: a boolean indicating whether the record's name was |
| specified by the TableGen input (if it is ``false``), or invented by |
| TableGen itself (if ``true``). |
| |
| For each variable defined in a record, the ``def`` object for that |
| record also has a key for the variable name. The corresponding value |
| is a translation into JSON of the variable's value, using the |
| conventions described below. |
| |
| Some TableGen data types are translated directly into the |
| corresponding JSON type: |
| |
| * A completely undefined value (e.g. for a variable declared without |
| initializer in some superclass of this record, and never initialized |
| by the record itself or any other superclass) is emitted as the JSON |
| ``null`` value. |
| |
| * ``int`` and ``bit`` values are emitted as numbers. Note that |
| TableGen ``int`` values are capable of holding integers too large to |
| be exactly representable in IEEE double precision. The integer |
| literal in the JSON output will show the full exact integer value. |
| So if you need to retrieve large integers with full precision, you |
| should use a JSON reader capable of translating such literals back |
| into 64-bit integers without losing precision, such as Python's |
| standard ``json`` module. |
| |
| * ``string`` and ``code`` values are emitted as JSON strings. |
| |
| * ``list<T>`` values, for any element type ``T``, are emitted as JSON |
| arrays. Each element of the array is represented in turn using these |
| same conventions. |
| |
| * ``bits`` values are also emitted as arrays. A ``bits`` array is |
| ordered from least-significant bit to most-significant. So the |
| element with index ``i`` corresponds to the bit described as |
| ``x{i}`` in TableGen source. However, note that this means that |
| scripting languages are likely to *display* the array in the |
| opposite order from the way it appears in the TableGen source or in |
| the diagnostic ``-print-records`` output. |
| |
| All other TableGen value types are emitted as a JSON object, |
| containing two standard fields: ``kind`` is a discriminator describing |
| which kind of value the object represents, and ``printable`` is a |
| string giving the same representation of the value that would appear |
| in ``-print-records``. |
| |
| * A reference to a ``def`` object has ``kind=="def"``, and has an |
| extra field ``def`` giving the name of the object referred to. |
| |
| * A reference to another variable in the same record has |
| ``kind=="var"``, and has an extra field ``var`` giving the name of |
| the variable referred to. |
| |
| * A reference to a specific bit of a ``bits``-typed variable in the |
| same record has ``kind=="varbit"``, and has two extra fields: |
| ``var`` gives the name of the variable referred to, and ``index`` |
| gives the index of the bit. |
| |
| * A value of type ``dag`` has ``kind=="dag"``, and has two extra |
| fields. ``operator`` gives the initial value after the opening |
| parenthesis of the dag initializer; ``args`` is an array giving the |
| following arguments. The elements of ``args`` are arrays of length |
| 2, giving the value of each argument followed by its colon-suffixed |
| name (if any). For example, in the JSON representation of the dag |
| value ``(Op 22, "hello":$foo)`` (assuming that ``Op`` is the name of |
| a record defined elsewhere with a ``def`` statement): |
| |
| * ``operator`` will be an object in which ``kind=="def"`` and |
| ``def=="Op"`` |
| |
| * ``args`` will be the array ``[[22, null], ["hello", "foo"]]``. |
| |
| * If any other kind of value or complicated expression appears in the |
| output, it will have ``kind=="complex"``, and no additional fields. |
| 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. |
| |
| SearchableTables Reference |
| -------------------------- |
| |
| A TableGen include file, ``SearchableTable.td``, provides classes for |
| generating C++ searchable tables. These tables are described in the |
| following sections. To generate the C++ code, run ``llvm-tblgen`` with the |
| ``--gen-searchable-tables`` option, which invokes the backend that generates |
| the tables from the records you provide. |
| |
| Each of the data structures generated for searchable tables is guarded by an |
| ``#ifdef``. This allows you to include the generated ``.inc`` file and select only |
| certain data structures for inclusion. The examples below show the macro |
| names used in these guards. |
| |
| Generic Enumerated Types |
| ~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The ``GenericEnum`` class makes it easy to define a C++ enumerated type and |
| the enumerated *elements* of that type. To define the type, define a record |
| whose parent class is ``GenericEnum`` and whose name is the desired enum |
| type. This class provides three fields, which you can set in the record |
| using the ``let`` statement. |
| |
| * ``string FilterClass``. The enum type will have one element for each record |
| that derives from this class. These records are collected to assemble the |
| complete set of elements. |
| |
| * ``string NameField``. The name of a field *in the collected records* that specifies |
| the name of the element. If a record has no such field, the record's |
| name will be used. |
| |
| * ``string ValueField``. The name of a field *in the collected records* that |
| specifies the numerical value of the element. If a record has no such |
| field, it will be assigned an integer value. Values are assigned in |
| alphabetical order starting with 0. |
| |
| Here is an example where the values of the elements are specified |
| explicitly, as a template argument to the ``BEntry`` class. The resulting |
| C++ code is shown. |
| |
| .. code-block:: text |
| |
| def BValues : GenericEnum { |
| let FilterClass = "BEntry"; |
| let NameField = "Name"; |
| let ValueField = "Encoding"; |
| } |
| |
| class BEntry<bits<16> enc> { |
| string Name = NAME; |
| bits<16> Encoding = enc; |
| } |
| |
| def BFoo : BEntry<0xac>; |
| def BBar : BEntry<0x14>; |
| def BZoo : BEntry<0x80>; |
| def BSnork : BEntry<0x4c>; |
| |
| .. code-block:: text |
| |
| #ifdef GET_BValues_DECL |
| enum BValues { |
| BBar = 20, |
| BFoo = 172, |
| BSnork = 76, |
| BZoo = 128, |
| }; |
| #endif |
| |
| In the following example, the values of the elements are assigned |
| automatically. Note that values are assigned from 0, in alphabetical order |
| by element name. |
| |
| .. code-block:: text |
| |
| def CEnum : GenericEnum { |
| let FilterClass = "CEnum"; |
| } |
| |
| class CEnum; |
| |
| def CFoo : CEnum; |
| def CBar : CEnum; |
| def CBaz : CEnum; |
| |
| .. code-block:: text |
| |
| #ifdef GET_CEnum_DECL |
| enum CEnum { |
| CBar = 0, |
| CBaz = 1, |
| CFoo = 2, |
| }; |
| #endif |
| |
| |
| Generic Tables |
| ~~~~~~~~~~~~~~ |
| |
| The ``GenericTable`` class is used to define a searchable generic table. |
| TableGen produces C++ code to define the table entries and also produces |
| the declaration and definition of a function to search the table based on a |
| primary key. To define the table, define a record whose parent class is |
| ``GenericTable`` and whose name is the name of the global table of entries. |
| This class provides six fields. |
| |
| * ``string FilterClass``. The table will have one entry for each record |
| that derives from this class. |
| |
| * ``string FilterClassField``. This is an optional field of ``FilterClass`` |
| which should be `bit` type. If specified, only those records with this field |
| being true will have corresponding entries in the table. This field won't be |
| included in generated C++ fields if it isn't included in ``Fields`` list. |
| |
| * ``string CppTypeName``. The name of the C++ struct/class type of the |
| table that holds the entries. If unspecified, the ``FilterClass`` name is |
| used. |
| |
| * ``list<string> Fields``. A list of the names of the fields *in the |
| collected records* that contain the data for the table entries. The order of |
| this list determines the order of the values in the C++ initializers. See |
| below for information about the types of these fields. |
| |
| * ``list<string> PrimaryKey``. The list of fields that make up the |
| primary key. |
| |
| * ``string PrimaryKeyName``. The name of the generated C++ function |
| that performs a lookup on the primary key. |
| |
| * ``bit PrimaryKeyEarlyOut``. See the third example below. |
| |
| TableGen attempts to deduce the type of each of the table fields so that it |
| can format the C++ initializers in the emitted table. It can deduce ``bit``, |
| ``bits<n>``, ``string``, ``Intrinsic``, and ``Instruction``. These can be |
| used in the primary key. Any other field types must be specified |
| explicitly; this is done as shown in the second example below. Such fields |
| cannot be used in the primary key. |
| |
| One special case of the field type has to do with code. Arbitrary code is |
| represented by a string, but has to be emitted as a C++ initializer without |
| quotes. If the code field was defined using a code literal (``[{...}]``), |
| then TableGen will know to emit it without quotes. However, if it was |
| defined using a string literal or complex string expression, then TableGen |
| will not know. In this case, you can force TableGen to treat the field as |
| code by including the following line in the ``GenericTable`` record, where |
| *xxx* is the code field name. |
| |
| .. code-block:: text |
| |
| string TypeOf_xxx = "code"; |
| |
| Here is an example where TableGen can deduce the field types. Note that the |
| table entry records are anonymous; the names of entry records are |
| irrelevant. |
| |
| .. code-block:: text |
| |
| def ATable : GenericTable { |
| let FilterClass = "AEntry"; |
| let FilterClassField = "IsNeeded"; |
| let Fields = ["Str", "Val1", "Val2"]; |
| let PrimaryKey = ["Val1", "Val2"]; |
| let PrimaryKeyName = "lookupATableByValues"; |
| } |
| |
| class AEntry<string str, int val1, int val2, bit isNeeded> { |
| string Str = str; |
| bits<8> Val1 = val1; |
| bits<10> Val2 = val2; |
| bit IsNeeded = isNeeded; |
| } |
| |
| def : AEntry<"Bob", 5, 3, 1>; |
| def : AEntry<"Carol", 2, 6, 1>; |
| def : AEntry<"Ted", 4, 4, 1>; |
| def : AEntry<"Alice", 4, 5, 1>; |
| def : AEntry<"Costa", 2, 1, 1>; |
| def : AEntry<"Dale", 2, 1, 0>; |
| |
| Here is the generated C++ code. The declaration of ``lookupATableByValues`` |
| is guarded by ``GET_ATable_DECL``, while the definitions are guarded by |
| ``GET_ATable_IMPL``. |
| |
| .. code-block:: text |
| |
| #ifdef GET_ATable_DECL |
| const AEntry *lookupATableByValues(uint8_t Val1, uint16_t Val2); |
| #endif |
| |
| #ifdef GET_ATable_IMPL |
| constexpr AEntry ATable[] = { |
| { "Costa", 0x2, 0x1 }, // 0 |
| { "Carol", 0x2, 0x6 }, // 1 |
| { "Ted", 0x4, 0x4 }, // 2 |
| { "Alice", 0x4, 0x5 }, // 3 |
| { "Bob", 0x5, 0x3 }, // 4 |
| /* { "Dale", 0x2, 0x1 }, // 5 */ // We don't generate this line as `IsNeeded` is 0. |
| }; |
| |
| const AEntry *lookupATableByValues(uint8_t Val1, uint16_t Val2) { |
| struct KeyType { |
| uint8_t Val1; |
| uint16_t Val2; |
| }; |
| KeyType Key = { Val1, Val2 }; |
| auto Table = ArrayRef(ATable); |
| auto Idx = std::lower_bound(Table.begin(), Table.end(), Key, |
| [](const AEntry &LHS, const KeyType &RHS) { |
| if (LHS.Val1 < RHS.Val1) |
| return true; |
| if (LHS.Val1 > RHS.Val1) |
| return false; |
| if (LHS.Val2 < RHS.Val2) |
| return true; |
| if (LHS.Val2 > RHS.Val2) |
| return false; |
| return false; |
| }); |
| |
| if (Idx == Table.end() || |
| Key.Val1 != Idx->Val1 || |
| Key.Val2 != Idx->Val2) |
| return nullptr; |
| return &*Idx; |
| } |
| #endif |
| |
| The table entries in ``ATable`` are sorted in order by ``Val1``, and within |
| each of those values, by ``Val2``. This allows a binary search of the table, |
| which is performed in the lookup function by ``std::lower_bound``. The |
| lookup function returns a reference to the found table entry, or the null |
| pointer if no entry is found. |
| |
| This example includes a field whose type TableGen cannot deduce. The ``Kind`` |
| field uses the enumerated type ``CEnum`` defined above. To inform TableGen |
| of the type, the record derived from ``GenericTable`` must include a string field |
| named ``TypeOf_``\ *field*, where *field* is the name of the field whose type |
| is required. |
| |
| .. code-block:: text |
| |
| def CTable : GenericTable { |
| let FilterClass = "CEntry"; |
| let Fields = ["Name", "Kind", "Encoding"]; |
| string TypeOf_Kind = "CEnum"; |
| let PrimaryKey = ["Encoding"]; |
| let PrimaryKeyName = "lookupCEntryByEncoding"; |
| } |
| |
| class CEntry<string name, CEnum kind, int enc> { |
| string Name = name; |
| CEnum Kind = kind; |
| bits<16> Encoding = enc; |
| } |
| |
| def : CEntry<"Apple", CFoo, 10>; |
| def : CEntry<"Pear", CBaz, 15>; |
| def : CEntry<"Apple", CBar, 13>; |
| |
| Here is the generated C++ code. |
| |
| .. code-block:: text |
| |
| #ifdef GET_CTable_DECL |
| const CEntry *lookupCEntryByEncoding(uint16_t Encoding); |
| #endif |
| |
| #ifdef GET_CTable_IMPL |
| constexpr CEntry CTable[] = { |
| { "Apple", CFoo, 0xA }, // 0 |
| { "Apple", CBar, 0xD }, // 1 |
| { "Pear", CBaz, 0xF }, // 2 |
| }; |
| |
| const CEntry *lookupCEntryByEncoding(uint16_t Encoding) { |
| struct KeyType { |
| uint16_t Encoding; |
| }; |
| KeyType Key = { Encoding }; |
| auto Table = ArrayRef(CTable); |
| auto Idx = std::lower_bound(Table.begin(), Table.end(), Key, |
| [](const CEntry &LHS, const KeyType &RHS) { |
| if (LHS.Encoding < RHS.Encoding) |
| return true; |
| if (LHS.Encoding > RHS.Encoding) |
| return false; |
| return false; |
| }); |
| |
| if (Idx == Table.end() || |
| Key.Encoding != Idx->Encoding) |
| return nullptr; |
| return &*Idx; |
| } |
| |
| The ``PrimaryKeyEarlyOut`` field, when set to 1, modifies the lookup |
| function so that it tests the first field of the primary key to determine |
| whether it is within the range of the collected records' primary keys. If |
| not, the function returns the null pointer without performing the binary |
| search. This is useful for tables that provide data for only some of the |
| elements of a larger enum-based space. The first field of the primary key |
| must be an integral type; it cannot be a string. |
| |
| Adding ``let PrimaryKeyEarlyOut = 1`` to the ``ATable`` above: |
| |
| .. code-block:: text |
| |
| def ATable : GenericTable { |
| let FilterClass = "AEntry"; |
| let Fields = ["Str", "Val1", "Val2"]; |
| let PrimaryKey = ["Val1", "Val2"]; |
| let PrimaryKeyName = "lookupATableByValues"; |
| let PrimaryKeyEarlyOut = 1; |
| } |
| |
| causes the lookup function to change as follows: |
| |
| .. code-block:: text |
| |
| const AEntry *lookupATableByValues(uint8_t Val1, uint16_t Val2) { |
| if ((Val1 < 0x2) || |
| (Val1 > 0x5)) |
| return nullptr; |
| |
| struct KeyType { |
| ... |
| |
| We can construct two GenericTables with the same ``FilterClass``, so that they |
| select from the same overall set of records, but assign them with different |
| ``FilterClassField`` values so that they include different subsets of the |
| records of that class. |
| |
| For example, we can create two tables that contain only even or odd records. |
| Fields ``IsEven`` and ``IsOdd`` won't be included in generated C++ fields |
| because they aren't included in ``Fields`` list. |
| |
| .. code-block:: text |
| |
| class EEntry<bits<8> value> { |
| bits<8> Value = value; |
| bit IsEven = !eq(!and(value, 1), 0); |
| bit IsOdd = !not(IsEven); |
| } |
| |
| foreach i = {1-10} in { |
| def : EEntry<i>; |
| } |
| |
| def EEntryEvenTable : GenericTable { |
| let FilterClass = "EEntry"; |
| let FilterClassField = "IsEven"; |
| let Fields = ["Value"]; |
| let PrimaryKey = ["Value"]; |
| let PrimaryKeyName = "lookupEEntryEvenTableByValue"; |
| } |
| |
| def EEntryOddTable : GenericTable { |
| let FilterClass = "EEntry"; |
| let FilterClassField = "IsOdd"; |
| let Fields = ["Value"]; |
| let PrimaryKey = ["Value"]; |
| let PrimaryKeyName = "lookupEEntryOddTableByValue"; |
| } |
| |
| The generated tables are: |
| |
| .. code-block:: text |
| |
| constexpr EEntry EEntryEvenTable[] = { |
| { 0x2 }, // 0 |
| { 0x4 }, // 1 |
| { 0x6 }, // 2 |
| { 0x8 }, // 3 |
| { 0xA }, // 4 |
| }; |
| |
| constexpr EEntry EEntryOddTable[] = { |
| { 0x1 }, // 0 |
| { 0x3 }, // 1 |
| { 0x5 }, // 2 |
| { 0x7 }, // 3 |
| { 0x9 }, // 4 |
| }; |
| |
| Search Indexes |
| ~~~~~~~~~~~~~~ |
| |
| The ``SearchIndex`` class is used to define additional lookup functions for |
| generic tables. To define an additional function, define a record whose parent |
| class is ``SearchIndex`` and whose name is the name of the desired lookup |
| function. This class provides three fields. |
| |
| * ``GenericTable Table``. The name of the table that is to receive another |
| lookup function. |
| |
| * ``list<string> Key``. The list of fields that make up the secondary key. |
| |
| * ``bit EarlyOut``. See the third example in `Generic Tables`_. |
| |
| Here is an example of a secondary key added to the ``CTable`` above. The |
| generated function looks up entries based on the ``Name`` and ``Kind`` fields. |
| |
| .. code-block:: text |
| |
| def lookupCEntry : SearchIndex { |
| let Table = CTable; |
| let Key = ["Name", "Kind"]; |
| } |
| |
| This use of ``SearchIndex`` generates the following additional C++ code. |
| |
| .. code-block:: text |
| |
| const CEntry *lookupCEntry(StringRef Name, unsigned Kind); |
| |
| ... |
| |
| const CEntry *lookupCEntryByName(StringRef Name, unsigned Kind) { |
| struct IndexType { |
| const char * Name; |
| unsigned Kind; |
| unsigned _index; |
| }; |
| static const struct IndexType Index[] = { |
| { "APPLE", CBar, 1 }, |
| { "APPLE", CFoo, 0 }, |
| { "PEAR", CBaz, 2 }, |
| }; |
| |
| struct KeyType { |
| std::string Name; |
| unsigned Kind; |
| }; |
| KeyType Key = { Name.upper(), Kind }; |
| auto Table = ArrayRef(Index); |
| auto Idx = std::lower_bound(Table.begin(), Table.end(), Key, |
| [](const IndexType &LHS, const KeyType &RHS) { |
| int CmpName = StringRef(LHS.Name).compare(RHS.Name); |
| if (CmpName < 0) return true; |
| if (CmpName > 0) return false; |
| if ((unsigned)LHS.Kind < (unsigned)RHS.Kind) |
| return true; |
| if ((unsigned)LHS.Kind > (unsigned)RHS.Kind) |
| return false; |
| return false; |
| }); |
| |
| if (Idx == Table.end() || |
| Key.Name != Idx->Name || |
| Key.Kind != Idx->Kind) |
| return nullptr; |
| return &CTable[Idx->_index]; |
| } |