[llvm] 473f8ae - [TableGen] Fix a couple of minor issues regarding the paste operator.
Paul C. Anagnostopoulos via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 2 09:22:32 PST 2020
Author: Paul C. Anagnostopoulos
Date: 2020-11-02T12:21:54-05:00
New Revision: 473f8ae69905bab3308d931e211ca9426da8b589
URL: https://github.com/llvm/llvm-project/commit/473f8ae69905bab3308d931e211ca9426da8b589
DIFF: https://github.com/llvm/llvm-project/commit/473f8ae69905bab3308d931e211ca9426da8b589.diff
LOG: [TableGen] Fix a couple of minor issues regarding the paste operator.
Update the documentation to fully describe it.
Differential Revision: https://reviews.llvm.org/D90617
Added:
Modified:
llvm/docs/TableGen/ProgRef.rst
llvm/lib/TableGen/TGParser.cpp
Removed:
################################################################################
diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst
index 47fac8d2a858..786319960d25 100644
--- a/llvm/docs/TableGen/ProgRef.rst
+++ b/llvm/docs/TableGen/ProgRef.rst
@@ -7,6 +7,14 @@ TableGen Programmer's Reference
.. contents::
:local:
+.. toctree::
+ :hidden:
+
+ BackEnds
+ BackGuide
+ Index
+ ../CommandGuide/tblgen
+
Introduction
============
@@ -106,7 +114,7 @@ multiple concrete records all at once. A multiclass can inherit from other
multiclasses, which means that the multiclass inherits all the definitions
from its parent multiclasses.
-`Appendix B: Sample Record`_ illustrates a complex record in the Intel X86
+`Appendix C: Sample Record`_ illustrates a complex record in the Intel X86
target and the simple way in which it is defined.
Source Files
@@ -316,8 +324,9 @@ Values and Expressions
There are many contexts in TableGen statements where a value is required. A
common example is in the definition of a record, where each field is
specified by a name and an optional value. TableGen allows for a reasonable
-number of
diff erent forms when building up values. These forms allow the
-TableGen file to be written in a syntax that is natural for the application.
+number of
diff erent forms when building up value expressions. These forms
+allow the TableGen file to be written in a syntax that is natural for the
+application.
Note that all of the values have rules for converting them from one type to
another. For example, these rules allow you to assign a value like ``7``
@@ -325,6 +334,7 @@ to an entity of type ``bits<4>``.
.. productionlist::
Value: `SimpleValue` `ValueSuffix`*
+ :| `Value` "#" `Value`
ValueSuffix: "{" `RangeList` "}"
:| "[" `RangeList` "]"
:| "." `TokIdentifier`
@@ -493,6 +503,28 @@ primary value. Here are the possible suffixes for some primary *value*.
The final value is the value of the specified *field* in the specified
record *value*.
+The paste operator
+------------------
+
+The paste operator (``#``) is the only infix operator availabe in TableGen
+expressions. It allows you to concatenate strings or lists, but has a few
+unusual features.
+
+The paste operator can be used when specifying the record name in a
+:token:`Def` or :token:`Defm` statement, in which case it must construct a
+string. If an operand is an undefined name (:token:`TokIdentifier`) or the
+name of a global :token:`Defvar` or :token:`Defset`, it is treated as a
+verbatim string of characters. The value of a global name is not used.
+
+The paste operator can be used in all other value expressions, in which case
+it can construct a string or a list. Rather oddly, but consistent with the
+previous case, if the *right-hand-side* operand is an undefined name or a
+global name, it is treated as a verbatim string of characters. The
+left-hand-side operand is treated normally.
+
+`Appendix B: Paste Operator Examples`_ presents examples of the behavior of
+the paste operator.
+
Statements
==========
@@ -614,11 +646,11 @@ A ``def`` statement defines a new concrete record.
.. productionlist::
Def: "def" [`NameValue`] `RecordBody`
- NameValue: `Value`
+ NameValue: `Value` (parsed in a special manner)
The name value is optional. If specified, it is parsed in a special mode
where undefined (unrecognized) identifiers are interpreted as literal
-strings. In particular, global identifiers are considered unrecognized.
+strings. In particular, global identifiers are considered unrecognized.
These include global variables defined by ``defvar`` and ``defset``.
If no name value is given, the record is *anonymous*. The final name of an
@@ -1657,12 +1689,6 @@ and non-0 as true.
This operator concatenates the string arguments *str1*, *str2*, etc., and
produces the resulting string.
-*str1*\ ``#``\ *str2*
- The paste operator (``#``) is a shorthand for
- ``!strconcat`` with two arguments. It can be used to concatenate operands that
- are not strings, in which
- case an implicit ``!cast<string>`` is done on those operands.
-
``!sub(``\ *a*\ ``,`` *b*\ ``)``
This operator subtracts *b* from *a* and produces the arithmetic
diff erence.
@@ -1684,8 +1710,61 @@ and non-0 as true.
the result. A logical XOR can be performed if all the arguments are either
0 or 1.
+Appendix B: Paste Operator Examples
+===================================
+
+Here is an example illustrating the use of the paste operator in record names.
+
+.. code-block:: text
+
+ defvar suffix = "_suffstring";
+ defvar some_ints = [0, 1, 2, 3];
+
+ def name # suffix {
+ }
+
+ foreach i = [1, 2] in {
+ def rec # i {
+ }
+ }
+
+The first ``def`` does not use the value of the ``suffix`` variable. The
+second def does use the value of the ``i`` iterator variable, because it is not a
+global name. The following records are produced.
+
+.. code-block:: text
+
+ def namesuffix {
+ }
+ def rec1 {
+ }
+ def rec2 {
+ }
+
+Here is a second example illustrating the paste operator in field value expressions.
+
+.. code-block:: text
+
+ def test {
+ string strings = suffix # suffix;
+ list<int> integers = some_ints # [4, 5, 6];
+ }
+
+The ``strings`` field expression uses ``suffix`` on both sides of the paste
+operator. It is evaluated normally on the left hand side, but taken verbatim
+on the right hand side. The ``integers`` field expression uses the value of
+the ``some_ints`` variable and a literal list. The following record is
+produced.
+
+.. code-block:: text
+
+ def test {
+ string strings = "_suffstringsuffix";
+ list<int> ints = [0, 1, 2, 3, 4, 5, 6];
+ }
+
-Appendix B: Sample Record
+Appendix C: Sample Record
=========================
One target machine supported by LLVM is the Intel x86. The following output
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index fcb007127772..a210351c1996 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -1972,7 +1972,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
if (ItemType) {
ListRecTy *ListType = dyn_cast<ListRecTy>(ItemType);
if (!ListType) {
- TokError(Twine("Type mismatch for list, expected list type, got ") +
+ TokError(Twine("Encountered a list when expecting a ") +
ItemType->getAsString());
return nullptr;
}
@@ -2219,6 +2219,8 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
if (isa<ListRecTy>(LHS->getType())) {
Lex.Lex(); // Eat the '#'.
+ assert(Mode == ParseValueMode && "encountered paste of lists in name");
+
switch (Lex.getCode()) {
case tgtok::colon:
case tgtok::semi:
@@ -2226,7 +2228,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType, IDParseMode Mode) {
Result = LHS; // trailing paste, ignore.
break;
default:
- Init *RHSResult = ParseValue(CurRec, ItemType, ParseNameMode);
+ Init *RHSResult = ParseValue(CurRec, ItemType, ParseValueMode);
if (!RHSResult)
return nullptr;
Result = BinOpInit::getListConcat(LHS, RHSResult);
More information about the llvm-commits
mailing list