183 Commits

Author SHA1 Message Date
Pengcheng Wang
d29c6a3425
[TabelGen] Use ID{n-m} for outer let statements (#187436)
I found this occasionally.

For outer let statements, if we want to override some bits, we specify
the range list in the form of `<n-m>`. But for inner let statements,
we use `{n-m}`.

This is inconsistent, and I can't find the reason why it is designed
as this. So here we make inner/outer let statements consistent and
remove the duplicated parsing functions.

There is only one in-tree usage so I think the impact is small.
2026-03-19 18:38:43 +08:00
Henrich Lauko
89d150a797
[TableGen] Add let append/prepend syntax for field concatenation (#182382)
## Motivation

LLVM TableGen currently lacks a way to **accumulate** field values
across class hierarchies. When a derived class sets a field via `let`,
it completely replaces the parent's value. This forces users into
verbose workarounds like:

```tablegen
class Op { // This is generic MLIR Base 
  code extraClassDeclaration = ?;
}

// Some Generic shared base
class MyShared1OpClass : Op {
  code shared1ExtraClassDeclaration = [{ some generic code 1 }];
}

class MyShared2OpClass : MyShared1OpClass {
  code shared2ExtraClassDeclaration = [{ some generic code 2 }];
}

def MyOp : MyShared2OpClass {
  // need to manually concatenate shared code
  let extraClassDeclaration =   
      shared1ExtraClassDeclaration
    # shared2ExtraClassDeclaration
    # [{ additional specialized code }]; 
}
```

Instead I propose a more natural incremental solution without
unnecessery intermediate definitions:

```
class Op {
  code extraClassDeclaration = ?;
}

class MyShared1OpClass : Op {
  let append extraClassDeclaration = [{ some generic code 1 }];
}

class MyShared2OpClass : MyShared1OpClass {
  let append extraClassDeclaration = [{ some generic code 2 }];
}

def MyOp : MyShared2OpClass {
  let append extraClassDeclaration = [{ additional specialized code }]; 
}
```

This is especially painful in MLIR, where dialect authors want base
op/type/attribute classes to inject shared C++ declarations into all
derived definitions. I attempted to solve this in PR
https://github.com/llvm/llvm-project/pull/182265 with MLIR-specific
`inheritableExtraClassDeclaration`/`Definition` fields, but as
@joker-eph [pointed
out](https://github.com/llvm/llvm-project/pull/182265#discussion_r2098718600),
this is ad-hoc -- the same inheritance problem exists for `traits`,
`arguments`, `results`, and any other list/string/dag field. Rather than
adding `inheritable*` variants per field, we should solve this at the
language level.

## Design

This PR adds two new modifiers to the `let` statement: **`append`** and
**`prepend`**.

```tablegen
class Base {
  list<int> items = [1, 2];
  string text = "hello";
  dag d = (op);
}

def Example : Base {
  let append items = [3, 4];    // items = [1, 2, 3, 4]
  let prepend items = [0];      // items = [0, 1, 2]
  let append text = " world";   // text = "hello world"
  let prepend text = "say ";    // text = "say hello"
  let append d = (op 3:$a);     // d = (op 3:$a)
}
```

### Supported types

| Field type | Operation | Concat operator |
|---|---|---|
| `list<T>` | append/prepend | `!listconcat` |
| `string` / `code` | append/prepend | `!strconcat` |
| `dag` | append/prepend | `!con` |
| Other (`bit`, `int`, `bits`) | -- | Error |

### Semantics

- **`let append`** concatenates the new value **after** the current
value
- **`let prepend`** concatenates the new value **before** the current
value
- If the current value is **unset** (`?`), the new value is used
directly
- A plain **`let`** (without modifier) still replaces, allowing opt-out
from accumulated values
- Works in both **body-level** (`def Foo { let append ... }`) and
**top-level** (`let append ... in { }`) contexts

### Multi-level inheritance

Accumulation works naturally across inheritance chains:

```tablegen
class Base {
  list<int> items = [1, 2];
}

class Middle : Base {
  let append items = [3];    // items = [1, 2, 3]
}

def Leaf : Middle {
  let append items = [4];    // items = [1, 2, 3, 4]
}
```

### Multiple inheritance

TableGen supports multiple inheritance (`def D : A, B { ... }`), where
parent classes are processed left to right and the **last parent class's
value wins** for any shared field. `let append`/`let prepend` operates
on whatever value the field has *after* inheritance resolution — it does
not accumulate across sibling parents:

```tablegen
class A { list<int> items = [1, 2]; }
class B { list<int> items = [3, 4]; }

def D : A, B {
  let append items = [5];  // items = [3, 4, 5]  (A's value is lost)
}
```

This also applies to diamond inheritance:

```tablegen
class Base  { list<int> items = [1]; }
class Left  : Base { let append items = [2]; }  // [1, 2]
class Right : Base { let append items = [3]; }  // [1, 3]

def D : Left, Right {
  let append items = [4];  // items = [1, 3, 4]  (Left's [2] is lost)
}
```

This is consistent with how plain `let` works with multiple inheritance
— it is the standard last-writer-wins rule. Users who need accumulation
from multiple parents should use a single-inheritance chain instead.

## Backward compatibility

This proposal is **fully backward compatible**. The keywords `append`
and `prepend` are implemented as **context-sensitive keywords** — they
are only recognized as modifiers when they appear immediately after
`let` (in both body-level and top-level contexts). In all other
positions, `append` and `prepend` remain valid identifiers and can be
used as field names, class names, def names, etc. This means:

- No existing `.td` files (in-tree or out-of-tree) will break
- Fields named `append` or `prepend` continue to work: `let append
append = [5];` is valid (the first `append` is the modifier, the second
is the field name)
- The parser checks for the identifier string value after `let`, not for
a reserved token

RFC:
https://discourse.llvm.org/t/rfc-tablegen-add-let-append-prepend-syntax-for-field-concatenation/89924/
2026-03-09 18:54:08 +01:00
Nick Sarnie
bc0af9901b
[TableGen] Allow specification of underlying type for GenericEnum (#183769)
Allow specification of the underlying C++ data type for `GenericEnum`.

I ran into this because I was trying to use a TableGen-genered enum in
`DenseSet` which requires the underlying type be specified.

Signed-off-by: Nick Sarnie <nick.sarnie@intel.com>
2026-03-02 15:09:23 +00:00
Jay Foad
6f5c214928
[TableGen] Remove deprecated !getop and !setop (#175155)
They have been deprecated for more than five years in favor of !getdagop
and !setdagop. See https://reviews.llvm.org/D89814.
2026-01-09 15:16:09 +00:00
Guillot Tony
22a2cae5d6
[Clang] Fix cleanup attribute by delaying type checks after the type is deduced (#164440)
Previously, the handling of the `cleanup` attribute had some checks
based on the type, but we were deducing the type after handling the
attribute.
This PR fixes the way the are dealing with type checks for the `cleanup`
attribute by delaying these checks after we are deducing the type.

It is also fixed in a way that the solution can be adapted for other
attributes that does some type based checks.
This is the list of C/C++ attributes that are doing type based checks
and will need to be fixed in additional PRs:
- CUDAShared
- MutualExclusions
- PassObjectSize
- InitPriority
- Sentinel
- AcquireCapability
- RequiresCapability
- LocksExcluded
- AcquireHandle

NB: Some attributes could have been missed in my shallow search.

Fixes #129631
2025-11-18 07:36:51 -05:00
Ivan Kosarev
71eaf14094
[TableGen] Split *GenRegisterInfo.inc. (#167700)
Reduces memory usage compiling backend sources, most notably for
AMDGPU by ~98 MB per source on average.

AMDGPUGenRegisterInfo.inc is tens of megabytes in size now, and
is even larger downstream. At the same time, it is included in
nearly all backend sources, typically just for a small portion of
its content, resulting in compilation being unnecessarily
memory-hungry, which in turn stresses buildbots and wastes their
resources.

Splitting .inc files also helps avoiding extra ccache misses
where changes in .td files don't cause changes in all parts of
what previously was a single .inc file.

It is thought that rather than building on top of the current
single-output-file design of TableGen, e.g., using `split-file`,
it would be more preferable to recognise the need for multi-file
outputs and give it a proper first-class support directly in
TableGen.
2025-11-14 16:30:51 +00:00
Kazu Hirata
d7c87c71b8
[llvm] Proofread TableGen/index.rst (#164756) 2025-10-23 07:08:55 -07:00
Kazu Hirata
a34e8c34d3
[llvm] Proofread TableGen/BackGuide.rst (#164365) 2025-10-21 07:22:48 -07:00
Kazu Hirata
ad3de39853
[llvm] Proofread TableGen/BackEnds.rst (#163918) 2025-10-17 07:27:44 -07:00
Kazu Hirata
c0a2bead5b
[llvm] Proofread TableGen/ProgRef.rst (#161629) 2025-10-02 09:27:17 -07:00
Kazu Hirata
5191cf090d
[llvm] Proofread BackGuide.rst (#151281) 2025-07-30 07:30:12 -07:00
Nemanja Ivanovic
144ae251aa
[TableGen] Improve handling for dag op names (#149248)
There are currently no ways to add names to dag
operators other than when defining them. Furthermore a !con operation as
well as some others, drops the operator names.
This patch propagates the name from the LHS dag
for !con and adds a way to get and set the operator name for a dag
(!getdagopname, !setdagopname).

---------

Co-authored-by: Nemanja Ivanovic <nemanja@synopsys.com>
2025-07-29 09:05:17 +02:00
Chenguang Wang
72de0e4584
[TableGen][Docs] Fix empty list syntax in TableGen doc. (#145041)
`[]<list<int>>` actually produces `list<list<int>>`.
2025-06-20 09:07:35 -07:00
Kazu Hirata
19a4e5202d
[llvm] Fix typos in documentation (#141078) 2025-05-22 13:58:42 -07:00
Jay Foad
2bc6f9d4b6
[TableGen] Only store direct superclasses in Record (#123072)
In Record only store the direct superclasses instead of all
superclasses. getSuperClasses recurses to find all superclasses when
necessary.

This gives a small reduction in memory usage. On lib/Target/X86/X86.td I
measured about 2.0% reduction in total bytes allocated (measured by
valgrind) and 1.3% reduction in peak memory usage (measured by
/usr/bin/time -v).

---------

Co-authored-by: Min-Yih Hsu <min@myhsu.dev>
2025-04-24 18:57:51 +01:00
Pengcheng Wang
883612859b
[TableGen] Add !instances operator to get defined records (#129680)
The format is: `!instances<T>([regex])`.
    
This operator produces a list of records whose type is `T`. If
`regex` is provided, only records whose name matches the regular
expression `regex` will be included. The format of `regex` is ERE
(Extended POSIX Regular Expressions).
2025-03-28 16:31:00 +08:00
Pengcheng Wang
376e3b62cd
[TableGen] Add !match operator to do regex matching (#130759)
The grammar is `!match(str, regex)` and this operator produces 1
if the `str` matches the regular expression `regex`.

The format of `regex` is ERE (Extended POSIX Regular Expressions).
2025-03-13 12:13:09 +08:00
Jay Foad
b275309a4c
[TableGen][Docs] Fix productionlists for assert and dump (#123739)
These were referring to nonexistent grammar tokens instead of `Value`.
2025-02-05 11:03:35 +00:00
Jay Foad
439de724fe
[TableGen][Docs] Fix productionlists for SimpleValue (#123751)
Previously the grammar tokens SimpleValue2 through SimpleValue9 were
unreferenced. This ties them together so that the grammar makes more
sense.
2025-02-05 09:15:38 +00:00
Jay Foad
104c2b86a5
[TableGen][Docs] Accept "code" as a Type (#124902)
Previously the Type production did not include "code", which was only
accepted in one place in the grammar:

   BodyItem: (`Type` | "code") `TokIdentifier` ["=" `Value`] ";"

However the parser implementation accepts "code" as a Type with only one
place where it is *not* allowed, corresponding to this production:

   SimpleValue9: `BangOperator` ["<" `Type` ">"] "(" `ValueListNE` ")"

This patch changes the production for Type to include "code", thereby
fixing most occurrences of Type in the grammar, and documents the
restriction for BangOperator Types in the text instead of codifying it
in the grammar.
2025-01-30 13:17:41 +00:00
Craig Topper
5ee8418057 [Docs][TableGen] Remove ReturnRange from the SearchIndex documentation. NFC
SearchIndex doesn't support ReturnRange. It is only supported for
the primary key.
2025-01-03 11:19:23 -08:00
Krzysztof Drewniak
b24caf3d2b
[llvm][TableGen] Add a !initialized predicate to allow testing for ? (#117964)
There are cases (like in an upcoming patch to MLIR's `Property` class)
where the ? value is a useful null value. However, existing predicates
make ti difficult to test if the value in a record one is operating is ?
or not.

This commit adds the !initialized predicate, which is 1 on concrete,
non-? values and 0 on ?.

---------

Co-authored-by: Akshat Oke <Akshat.Oke@amd.com>
2024-12-17 20:34:35 -06:00
Min-Yih Hsu
e8b70e9744
[TableGen] Make !and and !or short-circuit (#113963)
The idea is that by preemptively simplifying the result of `!and` and `!or`, we can fold
some of the conditional operators, like `!if` or `!cond`, as early as
possible.
2024-11-07 10:22:03 -08:00
Rahul Joshi
65e69f7436
[NFC][TableGen] Change Record::getSuperClasses to use const Record* (#110845)
Change `Record::getSuperClasses` to return a const pointer to the
superclass records.

This is a part of effort to have better const correctness in TableGen
backends:


https://discourse.llvm.org/t/psa-planned-changes-to-tablegen-getallderiveddefinitions-api-potential-downstream-breakages/81089
2024-10-02 13:24:46 -07:00
Rahul Joshi
66c8dce82e
[TableGen] Add a !listflatten operator to TableGen (#109346)
Add a !listflatten operator that will transform an input list of type
`list<list<X>>` to `list<X>` by concatenating elements of the
constituent lists of the input argument.
2024-09-24 06:01:34 -07:00
Garvit Gupta
6c903f05f3
[TableGen] Add support for emitting new function definition to return a range of results for Primary Key (#96174)
In the RISC-V architecture, multiple vendor-specific Control and Status
Registers (CSRs) share the same encoding. However, the existing lookup
function, which currently returns only a single result, falls short.
During disassembly, it consistently returns the first CSR encountered,
which may not be the correct CSR for the subtarget.

To address this issue, we modify the function definition to return a
range of results. These results can then be iterated upon to identify
the CSR that best fits the subtarget’s feature requirements. The
behavior of this new definition is controlled by a variable named
`ReturnRange`, which defaults to `false`.

Specifically, this patch introduces support for emitting a new lookup
function for the primary key. This function returns a pair of iterators
pointing to the first and last values, providing a comprehensive range
of values that satisfy the query
2024-07-11 10:54:31 -07:00
Piotr Fusik
a2cd846b7b
[TableGen][Docs] Clarify TokCode definition. (#96201)
"shortest" would be an empty sequence and the rule would never match.
2024-06-21 06:35:28 +02:00
Piotr Fusik
c659e3a3f8
[TableGen][Docs] Fix !range markup (#95540) 2024-06-17 16:53:57 +02:00
Jay Foad
18ec885a26
[RFC][AMDGPU] Remove old llvm.amdgcn.buffer.* and tbuffer intrinsics (#93801)
They have been superseded by llvm.amdgcn.raw.buffer.* and
llvm.amdgcn.struct.buffer.*.
2024-06-10 12:14:51 +01:00
Jason Eckhardt
8ae0485070
[TableGen] Extend direct lookup to instruction values in generic tables. (#80486)
Currently, for some tables involving a single primary key field which is
integral and densely numbered, a direct lookup is generated rather than
a binary search. This patch extends the direct lookup function
generation to instructions, where the integral value corresponds to the
instruction's enum value.

While this isn't as common as for other tables, it does occur in at
least one downstream backend and one in-tree backend.

Added a unit test and minimally updated the documentation.
2024-02-07 12:49:39 +08:00
Wang Pengcheng
acf6811d0f
[TableGen] Support type aliases via new keyword deftype
We can use `deftype` (not using `typedef` here to be consistent
with `def`, `defm`, `defset`, `defvar`, etc) to define type aliases.

Currently, only primitive types and type aliases are supported to be
the source type and `deftype` statements can only appear at the top
level.

Reviewers: fpetrogalli, Artem-B, nhaehnle, jroelofs

Reviewed By: jroelofs, nhaehnle, Artem-B

Pull Request: https://github.com/llvm/llvm-project/pull/79570
2024-02-02 17:41:47 +08:00
ostannard
56602a48c7
[TableGen] Include source location in JSON dump (#79028)
This adds a '!loc' field to each record containing the file name and
line number of the record declaration.
2024-01-24 17:07:20 +00:00
Kazu Hirata
211f5d00e2 [llvm] Fix typos in documentation 2023-12-17 15:36:44 -08:00
David Spickett
1e53386690 [llvm][TableGen][Docs] Add tools/resources links
This adds a link from the main docs page back to the README where
I have previously added a list of useful resources.

To that list, I've added a link to my recent llvm blog post.
2023-12-13 09:53:03 +00:00
Francesco Petrogalli
db9b6f4987
[Tablegen] Add keyword dump. (#68793)
The keyword is intended for debugging purpose. It prints a message to
stderr.

This patch is based on code originally written by Adam Nemet, and on the
feedback received by the reviewers in
https://reviews.llvm.org/D157492.
2023-10-19 09:26:36 +02:00
Aaron Ballman
670034c4b8 Fix LLVM sphinx bot 2023-10-11 08:42:52 -04:00
Francesco Petrogalli
cacfac416c
[TableGen] New bang operator !repr. (#68716)
The !repr operator represents the content of a variable or of a record
as a string.

This patch is based on code originally written by Adam Nemet, and on the
feedback received by the reviewers in
https://reviews.llvm.org/D157492.
2023-10-11 13:11:48 +02:00
wangpc
a904bb464f [TableGen] Format !range doc 2023-09-27 15:24:21 +08:00
Wang Pengcheng
df330d7496
[TableGen] Enhance !range bang operator (#66489)
We add a third argument `step` to `!range` bang operator to make it
with the same semantics as `range` in Python.

`step` can be negative. `step` is 1 by default and `step` can't be
0. If `start` < `end` and `step` is negative, or `start` > `end`
and `step` is positive, the result is an empty list.
2023-09-27 12:07:36 +08:00
Wang Pengcheng
2f780812ed
[TableGen] Add a field to filter out GenericTable entries (#65458)
A field `FilterClassField` is added to `GenericTable` class, which
is an optional bit field of `FilterClass`. If specified, only those
records with this field being true will have corresponding entries
in the table.
2023-09-08 16:27:11 +08:00
wangpc
91ccbc6c1c [TableGen] Support named arguments
We provide a way to specify arguments in the form of `name=value`
so that we don't have to specify all optional arguments before the
one we'd like to change. Required arguments can alse be specified
in this way.

Note that the argument can only be specified once regardless of
the way (named or positional) to specify and positional arguments
should be put before named arguments.

Reviewed By: reames

Differential Revision: https://reviews.llvm.org/D152998
2023-07-20 16:03:17 +08:00
Michael Liao
dcc8f9490f [TableGen] Add !setdagarg and !setdagname
- This patch proposes to add `!setdagarg` and `!setdagname` bang
  operators to produce a new DAG node after replacing the specified
  argument value/name from the given input DAG node. E.g.,
  `!setdagarg((foo 1, 2), 0, "x")` produces `(foo "x", 2)` and
  `!setdagname((foo 1:$a, 2:$b), 1, "c")` produces `(foo 1:$a, 2:$c)`.

Reviewed By: simon_tatham

Differential Revision: https://reviews.llvm.org/D151842
2023-06-07 09:37:40 -04:00
Michael Liao
26d7b7bb8f [TableGen] Add !getdagarg and !getdagname
- This patch proposes to add `!getdagarg` and `!getdagname` bang
  operators as the inverse operation of `!dag`. They allow us to examine
  arguments of a given dag.

Reviewed By: simon_tatham

Differential Revision: https://reviews.llvm.org/D151602
2023-05-31 10:54:43 -04:00
wangpc
45ea4d6256 [TableGen] Unify the priority of variables
In D148197, we have made `defvar` statement able to refer to class
template arguments. However, the priority of class/multiclass
template argument is higher than variables defined by `defvar`, which
is a little counterintuitive.

In this patch, we unify the priority of variables. Each pair of
braces introduces a new scope, which may contain some additional
variables like template arguments, loop iterators, etc. We can
define local variables inside this scope via `defvar` and these
variables are of higher priority than additional variables. This
means that `defvar` will shadow additional variables with the same
name. The scope can be nested, and we use the innermost variable.

This make variables defined by `defvar` prior to class/multiclass
template arguments, loop iterators, etc. The shadow rules now are:

* `V` in a record body shadows a global `V`.

* `V` in a record body shadows template argument `V`.

* `V` in template arguments shadows a global `V`.

* `V` in a `foreach` statement list shadows any `V` in surrounding record or global scopes.

Reviewed By: tra

Differential Revision: https://reviews.llvm.org/D149016
2023-05-24 12:44:14 +08:00
Kazu Hirata
96ddbd6dd8 [llvm] Fix typos in documentation 2023-05-12 23:47:46 -07:00
NAKAMURA Takumi
f98192af55 TableGen: Let expressions available to list subscriptions and list slices
This enables indexing in `!foreach` and permutation with `list[permlist]`.

Enhancements in syntax:

  - `list<int>` is applicable as a slice element.
  - `list[int,]` is evaluated as not `ElemType` but `list<ElemType>`
    with a single element.

Part of D145872

FIXME: I didn't apply new semantics to BitSlice.
2023-04-26 23:47:16 +09:00
NAKAMURA Takumi
cc20ca741b TableGen/ProgRef.rst: Fix copypasto in the description of !range 2023-04-26 23:47:15 +09:00
NAKAMURA Takumi
ab2187d786 TableGen: Introduce !range operator for half-opened interval
`!range(a, b)` generates a list `[a,b)`. `a` is optional and `0` by default.

  - `!range(-1, 4)` generates `[-1, 0, 1, 2, 3]`
  - `!range(4)` generates `[0, 1, 2, 3]`
  - `!range(2, 2)` generates `[]<list<int>>`

`!range(list)` is equivalent to `!range(0, !size(list))`.

Differential Revision: https://reviews.llvm.org/D145871
2023-04-25 22:38:20 +09:00
wangpc
41eafdf9aa [TableGen] Format document
Add missing bang operators and reorder them in alphabetical order.

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D146687
2023-03-27 11:27:35 +08:00
NAKAMURA Takumi
4178ef43b2 TableGen: Introduce llvm::TableGen::Emitter to register backends
`Opt(flag, func, desc)` registers an option into `Action`.

`OptClass<EmitterC>` is also available if `EmitterC(RK).run(OS)` is capable.

`Action` is defined as `ManagedStatic<cl::opt>` to guarantee to be created
when each registration of emitter is invoked.

`llvm::TableGenMain(argv0, MainFn)` invokes `Action` instead of `MainFn`

Differential Revision: https://reviews.llvm.org/D144351
2023-03-21 16:21:27 +09:00