Create New Dialect and bind it to Python (failed)

Hi everyone,

I’m new to mlir and I want to learn how to create a new dialect and bind it to python. But I got mistakes when generating _{Dialect_name}_ops_gen.py. The error message is

[1/1] Building /_test_ops_gen.py...
FAILED: binding/_test_ops_gen.py /home/flagerlee/mlir-test/build/binding/_test_ops_gen.py 
cd /home/flagerlee/mlir-test/build && /home/flagerlee/buddy-mlir/llvm/build/bin/mlir-tblgen -gen-python-op-bindings -bind-dialect=test -I /home/flagerlee/python-mlir-test/binding -I/home/flagerlee/buddy-mlir/llvm/llvm/include -I/home/flagerlee/buddy-mlir/llvm/build/include -I/home/flagerlee/buddy-mlir/llvm/mlir/include -I/home/flagerlee/buddy-mlir/llvm/build/tools/mlir/include -I/home/flagerlee/mlir-test/include -I/home/flagerlee/mlir-test/build/include /home/flagerlee/mlir-test/binding/test_mlir/TestOps.td --write-if-changed -o binding/_test_ops_gen.py -d binding/_test_ops_gen.py.d
error: The class 'PythonAttr' is not defined

I have no idea about this error and how can I avoid it. I’m using llvm version 8f966c. My file tree is

.
├── binding
│   ├── CMakeLists.txt
│   └── test_mlir
│       ├── TestOps.td
│       └── test.py
├── CMakeLists.txt
└── include
    ├── CMakeLists.txt
    ├── TestDialect.h
    ├── TestDialect.td
    ├── TestOps.h
    └── TestOps.td

include/TestDialect.td:

#ifndef TEST_BASE
#define TEST_BASE

include "mlir/IR/OpBase.td"

def Test_Dialect : Dialect {
    let name = "test";
    let cppNamespace = "::mlir::test";
}

#endif

include/TestOps.td:

#ifndef TEST_OPS
#define TEST_OPS

include "TestDialect.td"

class Test_Op<string mnemonic, list<Trait> traits = []> :
    Op<Test_Dialect, mnemonic, traits>;


#endif

include/TestDialect.h:

#ifndef MLIR_TESTDIALECT_H
#define MLIR_TESTDIALECT_H

#include "mlir/IR/Dialect.h"
#include "TestDialect.h.inc"

#endif

include/TestOps.h:

#ifndef MLIR_TESTOPS_TD_H
#define MLIR_TESTOPS_TD_H

#define GET_OP_CLASSES
#include "TestOps.h.inc"

#endif

include/CMakeLists.txt:

set(LLVM_TARGET_DEFINITIONS TestDialect.td)
mlir_tablegen(TestDialect.h.inc -gen-dialect-decls)
mlir_tablegen(TestDialect.cpp.inc -gen-dialect-defs)

set(LLVM_TARGET_DEFINITIONS TestOps.td)
mlir_tablegen(TestOps.h.inc -gen-op-decls)
mlir_tablegen(TestOps.cpp.inc -gen-op-defs)

add_public_tablegen_target(TestTableGen)

binding/test_mlir/TestOps.td:

#ifndef PYTHON_BINDINGS_TEST_OPS
#define PYTHON_BINDINGS_TEST_OPS

include "TestOps.td"

#endif

binding/test_mlir/test.py:

from ._test_ops_gen import *

binding/CMakeLists.txt:

include(AddMLIRPython)

set(TEST_MLIR_PYTHON_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/test_mlir")

declare_mlir_python_sources(TestMLIRPythonSources)

declare_mlir_python_sources(TestMLIRPythonSources.Dialects
        ADD_TO_PARENT TestMLIRPythonSources
        )

declare_mlir_dialect_python_bindings(
        ADD_TO_PARENT TestMLIRPythonSources.Dialects
        ROOT_DIR "${TEST_MLIR_PYTHON_ROOT_DIR}"
        TD_FILE TestOps.td
        SOURCES test.py
        DIALECT_NAME test
)

CMakeLists.txt:

cmake_minimum_required(VERSION 3.11)
project(test-mlir)

if (POLICY CMP0077)
    cmake_policy(SET CMP0077 NEW)
endif ()

if (POLICY CMP0116)
    cmake_policy(SET CMP0116 OLD)
endif ()

set(CMAKE_CXX_STANDARD 17)

find_package(MLIR REQUIRED CONFIG)
message(STATUS "Using MLIRConfig.cmake in: ${MLIR_DIR}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

set(LLVM_MLIR_BINARY_DIR ${MLIR_DIR}/../../../bin)
set(LLVM_MLIR_SOURCE_DIR ${MLIR_DIR}/../../../../mlir)
set(LLVM_PROJECT_SOURCE_DIR ${MLIR_DIR}/../../../../)

list(APPEND CMAKE_MODULE_PATH "${MLIR_CMAKE_DIR}")
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")

include(TableGen)
include(AddLLVM)
include(AddMLIR)
include(HandleLLVMOptions)

include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${MLIR_INCLUDE_DIRS})
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(${PROJECT_BINARY_DIR}/include)

add_subdirectory(include)
add_subdirectory(binding)
set(LLVM_LINK_COMPONENTS Support)

set(PYTHON_MLIR_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(PYTHON_MLIR_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")

You need to include this file https://github.com/llvm/llvm-project/blob/8f966cedea594d9a91e585e88a80a42c04049e6c/mlir/include/mlir/Bindings/Python/Attributes.td in your binding/test_mlir/TestOps.td. This is no longer necessary in more recent version of MLIR.

Thanks a lot! No wonder I didn’t see this file included in llvm-project and torch-mlir.