Skip to content

Commit 41035f4

Browse files
hhkitMoxinilianmath-fehr
authored
[MLIR][IRDL] Added IRDL to C++ Translation (#133982)
This PR introduces a new tool, mlir-irdl-to-cpp, that converts IRDL to C++ definitions. The C++ definitions allow use of the IRDL-defined dialect in MLIR C++ infrastructure, enabling the use of conversion patterns with IRDL dialects for example. This PR also adds CMake utilities to easily integrate the IRDL dialects into MLIR projects. Note that most IRDL features are not supported. In general, we are only able to define simple types and operations. - The only type constraint supported is `irdl.any`. - Variadic operands and results are not supported. - Verifiers for the IRDL constraints are not generated. - Attributes are not supported. --------- Co-authored-by: Théo Degioanni <[email protected]> Co-authored-by: Fehr Mathieu <[email protected]>
1 parent 5060f08 commit 41035f4

39 files changed

+1787
-23
lines changed

mlir/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ list(INSERT CMAKE_MODULE_PATH 0
6363
)
6464

6565
include(AddMLIR)
66+
include(IRDLToCpp)
6667

6768
# -BSymbolic is incompatible with TypeID
6869
if("${CMAKE_SHARED_LINKER_FLAGS}" MATCHES "-Bsymbolic[^-]")
@@ -206,6 +207,7 @@ include_directories(BEFORE
206207
# Adding tools/mlir-tblgen here as calling add_tablegen sets some variables like
207208
# MLIR_TABLEGEN_EXE in PARENT_SCOPE which gets lost if that folder is included
208209
# from another directory like tools
210+
add_subdirectory(tools/mlir-irdl-to-cpp)
209211
add_subdirectory(tools/mlir-linalg-ods-gen)
210212
add_subdirectory(tools/mlir-pdll)
211213
add_subdirectory(tools/mlir-tblgen)

mlir/cmake/modules/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ set(MLIR_CONFIG_TABLEGEN_EXE mlir-tblgen)
112112
set(MLIR_CONFIG_PDLL_TABLEGEN_EXE mlir-pdll)
113113
set(MLIR_CONFIG_SRC_SHARDER_TABLEGEN_EXE mlir-src-sharder)
114114

115+
set(MLIR_CONFIG_IRDL_TO_CPP_EXE mlir-irdl-to-cpp)
116+
115117
configure_file(
116118
${CMAKE_CURRENT_SOURCE_DIR}/MLIRConfig.cmake.in
117119
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/MLIRConfig.cmake
@@ -135,6 +137,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
135137
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/MLIRConfigVersion.cmake
136138
${CMAKE_CURRENT_SOURCE_DIR}/AddMLIR.cmake
137139
${CMAKE_CURRENT_SOURCE_DIR}/AddMLIRPython.cmake
140+
${CMAKE_CURRENT_SOURCE_DIR}/IRDLToCpp.cmake
138141
${CMAKE_CURRENT_SOURCE_DIR}/MLIRDetectPythonEnv.cmake
139142
DESTINATION ${MLIR_INSTALL_PACKAGE_DIR}
140143
COMPONENT mlir-cmake-exports)

mlir/cmake/modules/IRDLToCpp.cmake

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function(add_irdl_to_cpp_target target irdl_file)
2+
add_custom_command(
3+
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${irdl_file}.cpp.inc
4+
COMMAND ${MLIR_IRDL_TO_CPP_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/${irdl_file} -o ${CMAKE_CURRENT_BINARY_DIR}/${irdl_file}.cpp.inc
5+
6+
# The command output depends on the executable to ensure IRDL sources are properly rebuilt
7+
# if the tool changes.
8+
DEPENDS ${MLIR_IRDL_TO_CPP_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/${irdl_file}
9+
COMMENT "Building ${irdl_file}..."
10+
)
11+
add_custom_target(${target} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${irdl_file}.cpp.inc)
12+
endfunction()

mlir/cmake/modules/MLIRConfig.cmake.in

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ set(MLIR_INCLUDE_DIRS "@MLIR_CONFIG_INCLUDE_DIRS@")
1212
set(MLIR_TABLEGEN_EXE "@MLIR_CONFIG_TABLEGEN_EXE@")
1313
set(MLIR_PDLL_TABLEGEN_EXE "@MLIR_CONFIG_PDLL_TABLEGEN_EXE@")
1414
set(MLIR_SRC_SHARDER_TABLEGEN_EXE "@MLIR_CONFIG_SRC_SHARDER_TABLEGEN_EXE@")
15+
set(MLIR_IRDL_TO_CPP_EXE "@MLIR_CONFIG_IRDL_TO_CPP_EXE@")
1516
set(MLIR_INSTALL_AGGREGATE_OBJECTS "@MLIR_INSTALL_AGGREGATE_OBJECTS@")
1617
set(MLIR_ENABLE_BINDINGS_PYTHON "@MLIR_ENABLE_BINDINGS_PYTHON@")
1718
set(MLIR_ENABLE_EXECUTION_ENGINE "@MLIR_ENABLE_EXECUTION_ENGINE@")

mlir/include/mlir/Dialect/IRDL/IR/IRDLOps.td

+4
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def IRDL_TypeOp : IRDL_Op<"type",
9191
let regions = (region SizedRegion<1>:$body);
9292
let assemblyFormat =
9393
"$sym_name attr-dict-with-keyword custom<SingleBlockRegion>($body)";
94+
let hasVerifier = 1;
9495
}
9596

9697
def IRDL_AttributeOp : IRDL_Op<"attribute",
@@ -126,6 +127,8 @@ def IRDL_AttributeOp : IRDL_Op<"attribute",
126127
let regions = (region SizedRegion<1>:$body);
127128
let assemblyFormat =
128129
"$sym_name attr-dict-with-keyword custom<SingleBlockRegion>($body)";
130+
131+
let hasVerifier = 1;
129132
}
130133

131134
def IRDL_ParametersOp : IRDL_Op<"parameters",
@@ -202,6 +205,7 @@ def IRDL_OperationOp : IRDL_Op<"operation",
202205
let assemblyFormat =
203206
"$sym_name attr-dict-with-keyword custom<SingleBlockRegion>($body)";
204207
let hasRegionVerifier = true;
208+
let hasVerifier = 1;
205209
}
206210

207211
def IRDL_OperandsOp : IRDL_Op<"operands", [HasParent<"OperationOp">]> {

mlir/include/mlir/InitAllTranslations.h

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#ifndef MLIR_INITALLTRANSLATIONS_H
1515
#define MLIR_INITALLTRANSLATIONS_H
1616

17+
#include "mlir/Target/IRDLToCpp/TranslationRegistration.h"
18+
1719
namespace mlir {
1820

1921
void registerFromLLVMIRTranslation();
@@ -33,6 +35,7 @@ inline void registerAllTranslations() {
3335
static bool initOnce = []() {
3436
registerFromLLVMIRTranslation();
3537
registerFromSPIRVTranslation();
38+
registerIRDLToCppTranslation();
3639
registerToCppTranslation();
3740
registerToLLVMIRTranslation();
3841
registerToSPIRVTranslation();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===- IRDLToCpp.h - Register translation -----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines the registration function for the IRDL to C++ translation.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef MLIR_TARGET_IRDLTOCPP_IRDLTOCPP_H
14+
#define MLIR_TARGET_IRDLTOCPP_IRDLTOCPP_H
15+
16+
#include "mlir/Dialect/IRDL/IR/IRDL.h"
17+
18+
namespace mlir {
19+
namespace irdl {
20+
21+
/// Translates an IRDL dialect definition to a C++ definition that can be used
22+
/// with MLIR.
23+
///
24+
/// The following preprocessor macros will generate the following code:
25+
///
26+
/// // This define generates code for the dialect's class declarations
27+
/// #define GEN_DIALECT_DECL_HEADER
28+
///
29+
/// // This define generates code for the dialect's class definitions
30+
/// #define GEN_DIALECT_DEF
31+
LogicalResult
32+
translateIRDLDialectToCpp(llvm::ArrayRef<irdl::DialectOp> dialects,
33+
raw_ostream &output);
34+
35+
} // namespace irdl
36+
} // namespace mlir
37+
38+
#endif // MLIR_TARGET_IRDLTOCPP_IRDLTOCPP_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===- TranslationRegistration.h - Register translation ---------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines the registration function for the IRDL to C++ translation.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef MLIR_TARGET_IRDLTOCPP_TRANSLATIONREGISTRATION_H
14+
#define MLIR_TARGET_IRDLTOCPP_TRANSLATIONREGISTRATION_H
15+
16+
namespace mlir {
17+
18+
void registerIRDLToCppTranslation();
19+
20+
} // namespace mlir
21+
22+
#endif // MLIR_TARGET_IRDLTOCPP_TRANSLATIONREGISTRATION_H

mlir/lib/Dialect/IRDL/IR/IRDL.cpp

+53-12
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,62 @@ static void printSingleBlockRegion(OpAsmPrinter &p, Operation *op,
7474
if (!region.getBlocks().front().empty())
7575
p.printRegion(region);
7676
}
77+
static llvm::LogicalResult isValidName(llvm::StringRef in, mlir::Operation *loc,
78+
const Twine &label) {
79+
if (in.empty())
80+
return loc->emitError("name of ") << label << " is empty";
81+
82+
bool allowUnderscore = false;
83+
for (auto &elem : in) {
84+
if (elem == '_') {
85+
if (!allowUnderscore)
86+
return loc->emitError("name of ")
87+
<< label << " should not contain leading or double underscores";
88+
} else {
89+
if (!isalnum(elem))
90+
return loc->emitError("name of ")
91+
<< label
92+
<< " must contain only lowercase letters, digits and "
93+
"underscores";
94+
95+
if (llvm::isUpper(elem))
96+
return loc->emitError("name of ")
97+
<< label << " should not contain uppercase letters";
98+
}
99+
100+
allowUnderscore = elem != '_';
101+
}
102+
103+
return success();
104+
}
77105

78106
LogicalResult DialectOp::verify() {
79107
if (!Dialect::isValidNamespace(getName()))
80108
return emitOpError("invalid dialect name");
109+
if (failed(isValidName(getSymName(), getOperation(), "dialect")))
110+
return failure();
111+
81112
return success();
82113
}
83114

115+
LogicalResult OperationOp::verify() {
116+
return isValidName(getSymName(), getOperation(), "operation");
117+
}
118+
119+
LogicalResult TypeOp::verify() {
120+
auto symName = getSymName();
121+
if (symName.front() == '!')
122+
symName = symName.substr(1);
123+
return isValidName(symName, getOperation(), "type");
124+
}
125+
126+
LogicalResult AttributeOp::verify() {
127+
auto symName = getSymName();
128+
if (symName.front() == '#')
129+
symName = symName.substr(1);
130+
return isValidName(symName, getOperation(), "attribute");
131+
}
132+
84133
LogicalResult OperationOp::verifyRegions() {
85134
// Stores pairs of value kinds and the list of names of values of this kind in
86135
// the operation.
@@ -133,18 +182,10 @@ static LogicalResult verifyNames(Operation *op, StringRef kindName,
133182
DenseMap<StringRef, size_t> nameMap;
134183
for (auto [i, name] : llvm::enumerate(names)) {
135184
StringRef nameRef = llvm::cast<StringAttr>(name).getValue();
136-
if (nameRef.empty())
137-
return op->emitOpError()
138-
<< "name of " << kindName << " #" << i << " is empty";
139-
if (!llvm::isAlpha(nameRef[0]) && nameRef[0] != '_')
140-
return op->emitOpError()
141-
<< "name of " << kindName << " #" << i
142-
<< " must start with either a letter or an underscore";
143-
if (llvm::any_of(nameRef,
144-
[](char c) { return !llvm::isAlnum(c) && c != '_'; }))
145-
return op->emitOpError()
146-
<< "name of " << kindName << " #" << i
147-
<< " must contain only letters, digits and underscores";
185+
186+
if (failed(isValidName(nameRef, op, Twine(kindName) + " #" + Twine(i))))
187+
return failure();
188+
148189
if (nameMap.contains(nameRef))
149190
return op->emitOpError() << "name of " << kindName << " #" << i
150191
<< " is a duplicate of the name of " << kindName

mlir/lib/Target/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
add_subdirectory(Cpp)
2+
add_subdirectory(IRDLToCpp)
23
add_subdirectory(SPIRV)
34
add_subdirectory(LLVMIR)
45
add_subdirectory(LLVM)
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
add_mlir_translation_library(MLIRTargetIRDLToCpp
2+
TranslationRegistration.cpp
3+
IRDLToCpp.cpp
4+
Templates/DialectDecl.txt
5+
Templates/DialectDef.txt
6+
Templates/Header.txt
7+
Templates/PerOperationDecl.txt
8+
Templates/PerOperationDef.txt
9+
Templates/TypeDecl.txt
10+
Templates/TypeDef.txt
11+
Templates/TypeHeaderDecl.txt
12+
Templates/TypeHeaderDef.txt
13+
14+
LINK_LIBS PUBLIC
15+
MLIRIR
16+
MLIRIRDL
17+
MLIRTranslateLib
18+
)

0 commit comments

Comments
 (0)