2013-01-07 02:43:44 +00:00
|
|
|
===========================
|
|
|
|
TableGen Language Reference
|
|
|
|
===========================
|
|
|
|
|
|
|
|
.. sectionauthor:: Sean Silva <silvas@purdue.edu>
|
|
|
|
|
|
|
|
.. contents::
|
|
|
|
:local:
|
|
|
|
|
|
|
|
.. warning::
|
|
|
|
This document is extremely rough. If you find something lacking, please
|
|
|
|
fix it, file a documentation bug, or ask about it on llvmdev.
|
|
|
|
|
|
|
|
Introduction
|
|
|
|
============
|
|
|
|
|
|
|
|
This document is meant to be a normative spec about the TableGen language
|
|
|
|
in and of itself (i.e. how to understand a given construct in terms of how
|
|
|
|
it affects the final set of records represented by the TableGen file). If
|
|
|
|
you are unsure if this document is really what you are looking for, please
|
|
|
|
read :doc:`/TableGenFundamentals` first.
|
|
|
|
|
|
|
|
Notation
|
|
|
|
========
|
|
|
|
|
|
|
|
The lexical and syntax notation used here is intended to imitate
|
|
|
|
`Python's`_. In particular, for lexical definitions, the productions
|
|
|
|
operate at the character level and there is no implied whitespace between
|
|
|
|
elements. The syntax definitions operate at the token level, so there is
|
|
|
|
implied whitespace between tokens.
|
|
|
|
|
|
|
|
.. _`Python's`: http://docs.python.org/py3k/reference/introduction.html#notation
|
|
|
|
|
|
|
|
Lexical Analysis
|
|
|
|
================
|
|
|
|
|
|
|
|
TableGen supports BCPL (``// ...``) and nestable C-style (``/* ... */``)
|
|
|
|
comments.
|
|
|
|
|
|
|
|
The following is a listing of the basic punctuation tokens::
|
|
|
|
|
|
|
|
- + [ ] { } ( ) < > : ; . = ? #
|
|
|
|
|
|
|
|
Numeric literals take one of the following forms:
|
|
|
|
|
|
|
|
.. TableGen actually will lex some pretty strange sequences an interpret
|
|
|
|
them as numbers. What is shown here is an attempt to approximate what it
|
|
|
|
"should" accept.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
TokInteger: `DecimalInteger` | `HexInteger` | `BinInteger`
|
|
|
|
DecimalInteger: ["+" | "-"] ("0"..."9")+
|
|
|
|
HexInteger: "0x" ("0"..."9" | "a"..."f" | "A"..."F")+
|
|
|
|
BinInteger: "0b" ("0" | "1")+
|
|
|
|
|
|
|
|
One aspect to note is that the :token:`DecimalInteger` token *includes* the
|
|
|
|
``+`` or ``-``, as opposed to having ``+`` and ``-`` be unary operators as
|
|
|
|
most languages do.
|
|
|
|
|
|
|
|
TableGen has identifier-like tokens:
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
ualpha: "a"..."z" | "A"..."Z" | "_"
|
|
|
|
TokIdentifier: ("0"..."9")* `ualpha` (`ualpha` | "0"..."9")*
|
|
|
|
TokVarName: "$" `ualpha` (`ualpha` | "0"..."9")*
|
|
|
|
|
|
|
|
Note that unlike most languages, TableGen allows :token:`TokIdentifier` to
|
|
|
|
begin with a number. In case of ambiguity, a token will be interpreted as a
|
|
|
|
numeric literal rather than an identifier.
|
|
|
|
|
|
|
|
TableGen also has two string-like literals:
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
TokString: '"' <non-'"' characters and C-like escapes> '"'
|
|
|
|
TokCodeFragment: "[{" <shortest text not containing "}]"> "}]"
|
|
|
|
|
2013-01-09 02:20:30 +00:00
|
|
|
.. note::
|
|
|
|
The current implementation accepts the following C-like escapes::
|
|
|
|
|
|
|
|
\\ \' \" \t \n
|
|
|
|
|
2013-01-07 02:43:44 +00:00
|
|
|
TableGen also has the following keywords::
|
|
|
|
|
|
|
|
bit bits class code dag
|
|
|
|
def foreach defm field in
|
|
|
|
int let list multiclass string
|
|
|
|
|
|
|
|
TableGen also has "bang operators" which have a
|
2013-01-09 02:20:31 +00:00
|
|
|
wide variety of meanings:
|
2013-01-07 02:43:44 +00:00
|
|
|
|
2013-01-09 02:20:31 +00:00
|
|
|
.. productionlist::
|
|
|
|
BangOperator: one of
|
|
|
|
:!eq !if !head !tail !con
|
2013-01-25 14:49:08 +00:00
|
|
|
:!add !shl !sra !srl
|
2013-01-09 02:20:31 +00:00
|
|
|
:!cast !empty !subst !foreach !strconcat
|
2013-01-07 02:43:44 +00:00
|
|
|
|
|
|
|
Syntax
|
|
|
|
======
|
|
|
|
|
|
|
|
TableGen has an ``include`` mechanism. It does not play a role in the
|
|
|
|
syntax per se, since it is lexically replaced with the contents of the
|
|
|
|
included file.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
IncludeDirective: "include" `TokString`
|
|
|
|
|
|
|
|
TableGen's top-level production consists of "objects".
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
TableGenFile: `Object`*
|
|
|
|
Object: `Class` | `Def` | `Defm` | `Let` | `MultiClass` | `Foreach`
|
|
|
|
|
|
|
|
``class``\es
|
|
|
|
------------
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
Class: "class" `TokIdentifier` [`TemplateArgList`] `ObjectBody`
|
|
|
|
|
|
|
|
A ``class`` declaration creates a record which other records can inherit
|
|
|
|
from. A class can be parametrized by a list of "template arguments", whose
|
|
|
|
values can be used in the class body.
|
|
|
|
|
|
|
|
A given class can only be defined once. A ``class`` declaration is
|
|
|
|
considered to define the class if any of the following is true:
|
|
|
|
|
|
|
|
.. break ObjectBody into its consituents so that they are present here?
|
|
|
|
|
|
|
|
#. The :token:`TemplateArgList` is present.
|
|
|
|
#. The :token:`Body` in the :token:`ObjectBody` is present and is not empty.
|
|
|
|
#. The :token:`BaseClassList` in the :token:`ObjectBody` is present.
|
|
|
|
|
|
|
|
You can declare an empty class by giving and empty :token:`TemplateArgList`
|
|
|
|
and an empty :token:`ObjectBody`. This can serve as a restricted form of
|
|
|
|
forward declaration: note that records deriving from the forward-declared
|
|
|
|
class will inherit no fields from it since the record expansion is done
|
|
|
|
when the record is parsed.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
TemplateArgList: "<" `Declaration` ("," `Declaration`)* ">"
|
|
|
|
|
|
|
|
Declarations
|
|
|
|
------------
|
|
|
|
|
|
|
|
.. Omitting mention of arcane "field" prefix to discourage its use.
|
|
|
|
|
|
|
|
The declaration syntax is pretty much what you would expect as a C++
|
|
|
|
programmer.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
Declaration: `Type` `TokIdentifier` ["=" `Value`]
|
|
|
|
|
|
|
|
It assigns the value to the identifer.
|
|
|
|
|
|
|
|
Types
|
|
|
|
-----
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
Type: "string" | "code" | "bit" | "int" | "dag"
|
|
|
|
:| "bits" "<" `TokInteger` ">"
|
|
|
|
:| "list" "<" `Type` ">"
|
|
|
|
:| `ClassID`
|
|
|
|
ClassID: `TokIdentifier`
|
|
|
|
|
|
|
|
Both ``string`` and ``code`` correspond to the string type; the difference
|
|
|
|
is purely to indicate programmer intention.
|
|
|
|
|
|
|
|
The :token:`ClassID` must identify a class that has been previously
|
|
|
|
declared or defined.
|
|
|
|
|
|
|
|
Values
|
|
|
|
------
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
Value: `SimpleValue` `ValueSuffix`*
|
|
|
|
ValueSuffix: "{" `RangeList` "}"
|
|
|
|
:| "[" `RangeList` "]"
|
|
|
|
:| "." `TokIdentifier`
|
|
|
|
RangeList: `RangePiece` ("," `RangePiece`)*
|
|
|
|
RangePiece: `TokInteger`
|
|
|
|
:| `TokInteger` "-" `TokInteger`
|
|
|
|
:| `TokInteger` `TokInteger`
|
|
|
|
|
|
|
|
The peculiar last form of :token:`RangePiece` is due to the fact that the
|
|
|
|
"``-``" is included in the :token:`TokInteger`, hence ``1-5`` gets lexed as
|
|
|
|
two consecutive :token:`TokInteger`'s, with values ``1`` and ``-5``,
|
|
|
|
instead of "1", "-", and "5".
|
|
|
|
The :token:`RangeList` can be thought of as specifying "list slice" in some
|
|
|
|
contexts.
|
|
|
|
|
|
|
|
|
|
|
|
:token:`SimpleValue` has a number of forms:
|
|
|
|
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
SimpleValue: `TokIdentifier`
|
|
|
|
|
|
|
|
The value will be the variable referenced by the identifier. It can be one
|
|
|
|
of:
|
|
|
|
|
|
|
|
.. The code for this is exceptionally abstruse. These examples are a
|
|
|
|
best-effort attempt.
|
|
|
|
|
|
|
|
* name of a ``def``, such as the use of ``Bar`` in::
|
|
|
|
|
|
|
|
def Bar : SomeClass {
|
|
|
|
int X = 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
def Foo {
|
|
|
|
SomeClass Baz = Bar;
|
|
|
|
}
|
|
|
|
|
|
|
|
* value local to a ``def``, such as the use of ``Bar`` in::
|
|
|
|
|
|
|
|
def Foo {
|
|
|
|
int Bar = 5;
|
|
|
|
int Baz = Bar;
|
|
|
|
}
|
|
|
|
|
|
|
|
* a template arg of a ``class``, such as the use of ``Bar`` in::
|
|
|
|
|
|
|
|
class Foo<int Bar> {
|
|
|
|
int Baz = Bar;
|
|
|
|
}
|
|
|
|
|
|
|
|
* value local to a ``multiclass``, such as the use of ``Bar`` in::
|
|
|
|
|
|
|
|
multiclass Foo {
|
|
|
|
int Bar = 5;
|
|
|
|
int Baz = Bar;
|
|
|
|
}
|
|
|
|
|
|
|
|
* a template arg to a ``multiclass``, such as the use of ``Bar`` in::
|
|
|
|
|
|
|
|
multiclass Foo<int Bar> {
|
|
|
|
int Baz = Bar;
|
|
|
|
}
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
SimpleValue: `TokInteger`
|
|
|
|
|
|
|
|
This represents the numeric value of the integer.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
SimpleValue: `TokString`+
|
|
|
|
|
|
|
|
Multiple adjacent string literals are concatenated like in C/C++. The value
|
|
|
|
is the concatenation of the strings.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
SimpleValue: `TokCodeFragment`
|
|
|
|
|
|
|
|
The value is the string value of the code fragment.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
SimpleValue: "?"
|
|
|
|
|
|
|
|
``?`` represents an "unset" initializer.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
SimpleValue: "{" `ValueList` "}"
|
|
|
|
ValueList: [`ValueListNE`]
|
|
|
|
ValueListNE: `Value` ("," `Value`)*
|
|
|
|
|
|
|
|
This represents a sequence of bits, as would be used to initialize a
|
|
|
|
``bits<n>`` field (where ``n`` is the number of bits).
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
SimpleValue: `ClassID` "<" `ValueListNE` ">"
|
|
|
|
|
|
|
|
This generates a new anonymous record definition (as would be created by an
|
|
|
|
unnamed ``def`` inheriting from the given class with the given template
|
|
|
|
arguments) and the value is the value of that record definition.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
SimpleValue: "[" `ValueList` "]" ["<" `Type` ">"]
|
|
|
|
|
|
|
|
A list initializer. The optional :token:`Type` can be used to indicate a
|
|
|
|
specific element type, otherwise the element type will be deduced from the
|
|
|
|
given values.
|
|
|
|
|
|
|
|
.. The initial `DagArg` of the dag must start with an identifier or
|
|
|
|
!cast, but this is more of an implementation detail and so for now just
|
|
|
|
leave it out.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
SimpleValue: "(" `DagArg` `DagArgList` ")"
|
|
|
|
DagArgList: `DagArg` ("," `DagArg`)*
|
|
|
|
DagArg: `Value` [":" `TokVarName`]
|
|
|
|
|
|
|
|
The initial :token:`DagArg` is called the "operator" of the dag.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
SimpleValue: `BangOperator` ["<" `Type` ">"] "(" `ValueListNE` ")"
|
|
|
|
|
|
|
|
Bodies
|
|
|
|
------
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
ObjectBody: `BaseClassList` `Body`
|
|
|
|
BaseClassList: [`BaseClassListNE`]
|
|
|
|
BaseClassListNE: `SubClassRef` ("," `SubClassRef`)*
|
2013-01-09 02:20:24 +00:00
|
|
|
SubClassRef: (`ClassID` | `MultiClassID`) ["<" `ValueList` ">"]
|
2013-01-07 02:43:44 +00:00
|
|
|
DefmID: `TokIdentifier`
|
|
|
|
|
2013-01-09 02:20:24 +00:00
|
|
|
The version with the :token:`MultiClassID` is only valid in the
|
2013-01-07 02:43:44 +00:00
|
|
|
:token:`BaseClassList` of a ``defm``.
|
2013-01-09 02:20:24 +00:00
|
|
|
The :token:`MultiClassID` should be the name of a ``multiclass``.
|
2013-01-07 02:43:44 +00:00
|
|
|
|
|
|
|
.. put this somewhere else
|
|
|
|
|
|
|
|
It is after parsing the base class list that the "let stack" is applied.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
Body: ";" | "{" BodyList "}"
|
|
|
|
BodyList: BodyItem*
|
|
|
|
BodyItem: `Declaration` ";"
|
|
|
|
:| "let" `TokIdentifier` [`RangeList`] "=" `Value` ";"
|
|
|
|
|
|
|
|
The ``let`` form allows overriding the value of an inherited field.
|
|
|
|
|
|
|
|
``def``
|
|
|
|
-------
|
|
|
|
|
|
|
|
.. TODO::
|
|
|
|
There can be pastes in the names here, like ``#NAME#``. Look into that
|
|
|
|
and document it (it boils down to ParseIDValue with IDParseMode ==
|
|
|
|
ParseNameMode). ParseObjectName calls into the general ParseValue, with
|
|
|
|
the only different from "arbitrary expression parsing" being IDParseMode
|
|
|
|
== Mode.
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
Def: "def" `TokIdentifier` `ObjectBody`
|
|
|
|
|
|
|
|
Defines a record whose name is given by the :token:`TokIdentifier`. The
|
|
|
|
fields of the record are inherited from the base classes and defined in the
|
|
|
|
body.
|
|
|
|
|
|
|
|
Special handling occurs if this ``def`` appears inside a ``multiclass`` or
|
|
|
|
a ``foreach``.
|
|
|
|
|
|
|
|
``defm``
|
|
|
|
--------
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
Defm: "defm" `TokIdentifier` ":" `BaseClassList` ";"
|
|
|
|
|
|
|
|
Note that in the :token:`BaseClassList`, all of the ``multiclass``'s must
|
|
|
|
precede any ``class``'s that appear.
|
|
|
|
|
|
|
|
``foreach``
|
|
|
|
-----------
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
Foreach: "foreach" `Declaration` "in" "{" `Object`* "}"
|
|
|
|
:| "foreach" `Declaration` "in" `Object`
|
|
|
|
|
|
|
|
The value assigned to the variable in the declaration is iterated over and
|
|
|
|
the object or object list is reevaluated with the variable set at each
|
|
|
|
iterated value.
|
|
|
|
|
|
|
|
Top-Level ``let``
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
Let: "let" `LetList` "in" "{" `Object`* "}"
|
|
|
|
:| "let" `LetList` "in" `Object`
|
|
|
|
LetList: `LetItem` ("," `LetItem`)*
|
|
|
|
LetItem: `TokIdentifier` [`RangeList`] "=" `Value`
|
|
|
|
|
|
|
|
This is effectively equivalent to ``let`` inside the body of a record
|
|
|
|
except that it applies to multiple records at a time. The bindings are
|
|
|
|
applied at the end of parsing the base classes of a record.
|
|
|
|
|
|
|
|
``multiclass``
|
|
|
|
--------------
|
|
|
|
|
|
|
|
.. productionlist::
|
|
|
|
MultiClass: "multiclass" `TokIdentifier` [`TemplateArgList`]
|
2013-01-09 02:11:55 +00:00
|
|
|
: [":" `BaseMultiClassList`] "{" `MultiClassObject`+ "}"
|
2013-01-07 02:43:44 +00:00
|
|
|
BaseMultiClassList: `MultiClassID` ("," `MultiClassID`)*
|
|
|
|
MultiClassID: `TokIdentifier`
|
2013-01-09 02:11:55 +00:00
|
|
|
MultiClassObject: `Def` | `Defm` | `Let` | `Foreach`
|