Reuse Components of one dialect (Type, Attrs, Enums) from another Dialect

Hi, I am working on a setup where I have 2 Dialect: A stable, API-like dialect, let’s call it ToyStable dialect, and a more experimental, fast-changing dialect, let’s call it ToyInternal dialect.

I want to reuse some of the enums / attributes / types defined in ToyStable from ToyInternal.

I tried writing this in ToyInternalOps.td:

include "path/to/ToyStableBase.td"

Is this something supported in MLIR ? I might not have looked well enough, but I couldn’t find any example of one dialect td file including another dialect td file. (With the exception of the Builtin Dialect).

I came across one issue I couldn’t solve. The linker complains about multiple definition

duplicate symbol 'mlir::toy_stable::symbolizeMyToyEnum(unsigned int)' in:
    src/Dialect/ToyStable/IR/libMLIRToyStable.a
    src/Dialect/ToyInternal/IR/libMLIRToyInternal.a

This is because of this rule:

set(LLVM_TARGET_DEFINITIONS ToyInternalOps.td)
mlir_tablegen(Enums.h.inc -gen-enum-decls)
mlir_tablegen(Enums.cpp.inc -gen-enum-defs)

ToyInternalOps.td contains the ToyStable enums, and generate their definition. I was hoping to have an option equivalent to -attrdefs-dialect=xxx, but for enums. But it seems such option doesn’t exist. Is it missing ?

Another solution would be to create ToyStableEnums.td, ToyStableAttrs.td, ToyStableTypes.td, and update LLVM_TARGET_DEFINITIONS for every mlir_tablegen rule, but if feels like too much division. And I haven’t seen any upstream dialect having this many TD files.

Do you have any other ideas / suggestions. Perhaps my overall design could be improved.
Thanks.

Is there a specific reason why -enumdefs-dialect=xxx option is not implemented ? I am not familiar at all with tablegen, is it more complicated than for the other existing ones (like -attrdefs-dialect=xxx)

It is supported. For example, the memref dialect depends on the arith dialect: https://github.com/llvm/llvm-project/blob/3889c8214d1b4fcaa54f18b0944faa026f97b8ba/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td#L12. There are more dialects that depend on fastmath flags defined in arith. And many downstreams depend on types defined in other dialects.

It is generally a good idea to split the parts that need to be reusable into a separate ToyStableBase.td file and only include that instead of including ToyStableOps.td from ToyInternalOps.td. And yes, there is currently no way to filter out enum definitions by dialect.

The transform dialect, for example, has 6 TD files: https://github.com/llvm/llvm-project/tree/main/mlir/include/mlir/Dialect/Transform/IR. It is one of the most recently added, so it likely follows the most recent best practices.

This applies: FAQ - MLIR

Thank you, I didn’t know about the transform Dialect, I ended up taking a similar approach were I create a ToyStableAttrs.td file with all the attrs and enum definitions, which isn’t included in ToyInternalAttrs.td, hence resolving the double definition issue.
It’s still worth it despite the bit of refactoring needed over the dialect to extract all attributes in one file.