summaryrefslogtreecommitdiffstats
path: root/llvm/docs/TableGen
diff options
context:
space:
mode:
authorSimon Tatham <simon.tatham@arm.com>2020-01-14 09:10:18 +0000
committerSimon Tatham <simon.tatham@arm.com>2020-01-14 10:19:53 +0000
commit3388b0f59dcc7813278c753f96b66229f290cc59 (patch)
treed64f8dcbead51b2deb74e75afe7f86b4516bb5e5 /llvm/docs/TableGen
parent45924eb4671692b3fa9fd52fe39c81ec0647a848 (diff)
downloadbcm5719-llvm-3388b0f59dcc7813278c753f96b66229f290cc59.tar.gz
bcm5719-llvm-3388b0f59dcc7813278c753f96b66229f290cc59.zip
[TableGen] Introduce a `defvar` statement.
Summary: This allows you to define a global or local variable to an arbitrary value, and refer to it in subsequent definitions. The main use I anticipate for this is if you have to compute some difficult function of the parameters of a multiclass, and then use it many times. For example: multiclass Foo<int i, string s> { defvar op = !cast<BaseClass>("whatnot_" # s # "_" # i); def myRecord { dag a = (op this, (op that, the other), (op x, y, z)); int b = op.subfield; } def myOtherRecord<"template params including", op>; } There are a couple of ways to do this already, but they're not really satisfactory. You can replace `defvar x = y` with a loop over a singleton list, `foreach x = [y] in { ... }` - but that's unintuitive to someone who hasn't seen that workaround idiom before, and requires an extra pair of braces that you often didn't really want. Or you can define a nested pair of multiclasses, with the inner one taking `x` as a template parameter, and the outer one instantiating it just once with the desired value of `x` computed from its other parameters - but that makes it awkward to sequentially compute each value based on the previous ones. I think `defvar` makes things considerably easier. You can also use `defvar` at the top level, where it inserts globals into the same map used by `defset`. That allows you to define global constants without having to make a dummy record for them to live in: defvar MAX_BUFSIZE = 512; // previously: // def Dummy { int MAX_BUFSIZE = 512; } // and then refer to Dummy.MAX_BUFSIZE everywhere Reviewers: nhaehnle, hfinkel Reviewed By: hfinkel Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D71407
Diffstat (limited to 'llvm/docs/TableGen')
-rw-r--r--llvm/docs/TableGen/LangRef.rst41
1 files changed, 36 insertions, 5 deletions
diff --git a/llvm/docs/TableGen/LangRef.rst b/llvm/docs/TableGen/LangRef.rst
index 8f8b3613db5..7cbe6d99643 100644
--- a/llvm/docs/TableGen/LangRef.rst
+++ b/llvm/docs/TableGen/LangRef.rst
@@ -124,8 +124,8 @@ TableGen's top-level production consists of "objects".
.. productionlist::
TableGenFile: `Object`*
- Object: `Class` | `Def` | `Defm` | `Defset` | `Let` | `MultiClass` |
- `Foreach`
+ Object: `Class` | `Def` | `Defm` | `Defset` | `Defvar` | `Let` |
+ `MultiClass` | `Foreach`
``class``\es
------------
@@ -262,7 +262,7 @@ of:
foreach i = 0-5 in
def Foo#i;
-* a variable defined by ``defset``
+* a variable defined by ``defset`` or ``defvar``
* the implicit template argument ``NAME`` in a ``class`` or ``multiclass``
@@ -348,6 +348,7 @@ It is after parsing the base class list that the "let stack" is applied.
BodyList: BodyItem*
BodyItem: `Declaration` ";"
:| "let" `TokIdentifier` [ "{" `RangeList` "}" ] "=" `Value` ";"
+ :| `Defvar`
The ``let`` form allows overriding the value of an inherited field.
@@ -359,8 +360,8 @@ The ``let`` form allows overriding the value of an inherited field.
Defines a record whose name is given by the optional :token:`Value`. The value
is parsed in a special mode where global identifiers (records and variables
-defined by ``defset``) are not recognized, and all unrecognized identifiers
-are interpreted as strings.
+defined by ``defset``, and variables defined at global scope by ``defvar``) are
+not recognized, and all unrecognized identifiers are interpreted as strings.
If no name is given, the record is anonymous. The final name of anonymous
records is undefined, but globally unique.
@@ -420,6 +421,36 @@ The given type must be ``list<A>``, where ``A`` is some class. It is an error
to define a record (via ``def`` or ``defm``) inside the braces which doesn't
derive from ``A``.
+``defvar``
+----------
+.. productionlist::
+ Defvar: "defvar" `TokIdentifier` "=" `Value` ";"
+
+The identifier on the left of the ``=`` is defined to be a global or local
+variable, whose value is given by the expression on the right of the ``=``. The
+type of the variable is automatically inferred.
+
+A ``defvar`` statement at the top level of the file defines a global variable,
+in the same scope used by ``defset``. If a ``defvar`` statement appears inside
+any other construction, including classes, multiclasses and ``foreach``
+statements, then the variable is scoped to the inside of that construction
+only.
+
+In contexts where the ``defvar`` statement will be encountered multiple times,
+the definition is re-evaluated for each instance. For example, a ``defvar``
+inside a ``foreach`` can construct a value based on the iteration variable,
+which will be different every time round the loop; a ``defvar`` inside a
+templated class or multiclass can have a definition depending on the template
+parameters.
+
+Variables local to a ``foreach`` go out of scope at the end of each loop
+iteration, so their previous value is not accessible in the next iteration. (It
+won't work to ``defvar i=!add(i,1)`` each time you go round the loop.)
+
+In general, ``defvar`` variables are immutable once they are defined. It is an
+error to define the same variable name twice in the same scope (but legal to
+shadow the first definition temporarily in an inner scope).
+
``foreach``
-----------
OpenPOWER on IntegriCloud