Skip to content

Commit a534896

Browse files
flemairen6lforg37Ferdinand LemaireJessica PaquetteLuc Forget
authored
[MLIR][Wasm] Introduce the WasmSSA MLIR dialect (#149233)
Introduce the WasmSSA dialect as discussed in https://discourse.llvm.org/t/rfc-mlir-dialect-for-webassembly/86758 and during the ODM https://discourse.llvm.org/t/mlir-open-meeting-webassembly-dialect/86928 This PR only introduces the dialect definition and interfaces, the list of operators and some operators-related helper functions (related to parsing or verification) and some tests for those. Follow-up PRs will bring the binary Webassembly importer and the lowerings to other dialects along with testing and a driver for conversion of Webassembly binaries to LLVM IR. Co-authored-by: Luc Forget <[email protected]> Co-authored-by: Ferdinand Lemaire <[email protected]> Co-authored-by: Jessica Paquette <[email protected]> Co-authored-by: Luc Forget <[email protected]>
1 parent 76d98cf commit a534896

24 files changed

+2351
-0
lines changed

mlir/include/mlir/Dialect/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,6 @@ add_subdirectory(Transform)
4141
add_subdirectory(UB)
4242
add_subdirectory(Utils)
4343
add_subdirectory(Vector)
44+
add_subdirectory(WasmSSA)
4445
add_subdirectory(X86Vector)
4546
add_subdirectory(XeGPU)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(IR)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
set(LLVM_TARGET_DEFINITIONS WasmSSATypes.td)
2+
mlir_tablegen(WasmSSATypeConstraints.h.inc -gen-type-constraint-decls)
3+
mlir_tablegen(WasmSSATypeConstraints.cpp.inc -gen-type-constraint-defs)
4+
5+
set (LLVM_TARGET_DEFINITIONS WasmSSAInterfaces.td)
6+
mlir_tablegen(WasmSSAInterfaces.h.inc -gen-op-interface-decls)
7+
mlir_tablegen(WasmSSAInterfaces.cpp.inc -gen-op-interface-defs)
8+
add_public_tablegen_target(MLIRWasmSSAInterfacesIncGen)
9+
10+
set(LLVM_TARGET_DEFINITIONS WasmSSAOps.td)
11+
12+
add_mlir_dialect(WasmSSAOps wasmssa)
13+
add_mlir_doc(WasmSSAOps WasmSSAOps Dialects/ -gen-dialect-doc)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//===- WasmSSA.h - WasmSSA dialect ------------------*- 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+
#ifndef MLIR_DIALECT_WasmSSA_IR_WasmSSA_H_
10+
#define MLIR_DIALECT_WasmSSA_IR_WasmSSA_H_
11+
12+
#include "mlir/Bytecode/BytecodeOpInterface.h"
13+
#include "mlir/IR/Dialect.h"
14+
15+
//===----------------------------------------------------------------------===//
16+
// WebAssemblyDialect
17+
//===----------------------------------------------------------------------===//
18+
19+
#include "mlir/Dialect/WasmSSA/IR/WasmSSAOpsDialect.h.inc"
20+
21+
//===----------------------------------------------------------------------===//
22+
// WebAssembly Dialect Types
23+
//===----------------------------------------------------------------------===//
24+
25+
#define GET_TYPEDEF_CLASSES
26+
#include "mlir/Dialect/WasmSSA/IR/WasmSSAOpsTypes.h.inc"
27+
28+
//===----------------------------------------------------------------------===//
29+
// WebAssembly Interfaces
30+
//===----------------------------------------------------------------------===//
31+
32+
#include "mlir/Dialect/WasmSSA/IR/WasmSSAInterfaces.h"
33+
34+
//===----------------------------------------------------------------------===//
35+
// WebAssembly Dialect Operations
36+
//===----------------------------------------------------------------------===//
37+
#include "mlir/IR/SymbolTable.h"
38+
#include "mlir/Interfaces/CallInterfaces.h"
39+
#include "mlir/Interfaces/FunctionInterfaces.h"
40+
#include "mlir/Interfaces/InferTypeOpInterface.h"
41+
42+
//===----------------------------------------------------------------------===//
43+
// WebAssembly Constraints
44+
//===----------------------------------------------------------------------===//
45+
46+
namespace mlir {
47+
namespace wasmssa {
48+
#include "mlir/Dialect/WasmSSA/IR/WasmSSATypeConstraints.h.inc"
49+
}
50+
} // namespace mlir
51+
52+
#define GET_OP_CLASSES
53+
#include "mlir/Dialect/WasmSSA/IR/WasmSSAOps.h.inc"
54+
55+
#endif // MLIR_DIALECT_WasmSSA_IR_WasmSSA_H_
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===- WasmSSABase.td - Base defs for wasmssa dialect -*- tablegen -*-==//
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+
#ifndef WasmSSA_BASE
10+
#define WasmSSA_BASE
11+
12+
include "mlir/IR/EnumAttr.td"
13+
include "mlir/IR/OpBase.td"
14+
15+
def WasmSSA_Dialect : Dialect {
16+
let name = "wasmssa";
17+
let cppNamespace = "::mlir::wasmssa";
18+
let description = [{
19+
The `wasmssa` dialect is intended to represent WebAssembly
20+
modules in SSA form for easier manipulation.
21+
}];
22+
let useDefaultTypePrinterParser = true;
23+
}
24+
25+
#endif //WasmSSA_BASE
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//===- WasmSSAInterfaces.h - WasmSSA Interfaces ---*- 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 op interfaces for the WasmSSA dialect in MLIR.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef MLIR_DIALECT_WasmSSA_IR_WasmSSAINTERFACES_H_
14+
#define MLIR_DIALECT_WasmSSA_IR_WasmSSAINTERFACES_H_
15+
16+
#include "mlir/IR/BuiltinAttributes.h"
17+
#include "mlir/IR/OpDefinition.h"
18+
19+
namespace mlir::wasmssa {
20+
namespace detail {
21+
/// Verify that `op` conforms to the ConstantExpressionInterface.
22+
/// `op` must be initialized with valid constant expressions.
23+
LogicalResult verifyConstantExpressionInterface(Operation *op);
24+
25+
/// Verify that `op` conforms to the LabelBranchingOpInterface
26+
/// Checks that the branching is targetting something within its scope.
27+
LogicalResult verifyLabelBranchingOpInterface(Operation *op);
28+
29+
/// Verify that `op` conforms to LabelLevelInterfaceIsTerminator
30+
template <typename OpType>
31+
LogicalResult verifyLabelLevelInterfaceIsTerminator() {
32+
static_assert(OpType::template hasTrait<::mlir::OpTrait::IsTerminator>(),
33+
"LabelLevelOp should be terminator ops");
34+
return success();
35+
}
36+
37+
/// Verify that `op` conforms to the LabelLevelInterface
38+
/// `op`'s target should defined at the same scope level.
39+
LogicalResult verifyLabelLevelInterface(Operation *op);
40+
} // namespace detail
41+
42+
/// Operations implementing this trait are considered as valid
43+
/// constant expressions in any context (In contrast of
44+
/// ConstantExprCheckOpInterface which are sometimes considered valid constant
45+
/// expressions.
46+
template <class OperationType>
47+
struct ConstantExprOpTrait
48+
: public OpTrait::TraitBase<OperationType, ConstantExprOpTrait> {};
49+
50+
/// Trait used to verify operations that need a constant expression initializer.
51+
template <typename OpType>
52+
struct ConstantExpressionInitializerOpTrait
53+
: public OpTrait::TraitBase<OpType, ConstantExpressionInitializerOpTrait> {
54+
static LogicalResult verifyTrait(Operation *op) {
55+
return detail::verifyConstantExpressionInterface(op);
56+
}
57+
};
58+
59+
} // namespace mlir::wasmssa
60+
#include "mlir/Dialect/WasmSSA/IR/WasmSSAInterfaces.h.inc"
61+
62+
#endif // MLIR_DIALECT_WasmSSA_IR_WasmSSAINTERFACES_H_
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
//===-- WasmSSAInterfaces.td - WasmSSA Interfaces -*- tablegen -*--===//
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 interfaces for the WasmSSA dialect in MLIR.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef WasmSSA_INTERFACES
14+
#define WasmSSA_INTERFACES
15+
16+
include "mlir/IR/OpBase.td"
17+
include "mlir/IR/BuiltinAttributes.td"
18+
19+
def LabelLevelOpInterface : OpInterface<"LabelLevelOpInterface"> {
20+
let cppNamespace = "::mlir::wasmssa";
21+
let description = [{
22+
Operation that defines one level of nesting for Wasm branching.
23+
24+
These ops defines Wasm control flow nesting levels (Wasm Labels) that Wasm
25+
branching operations can target.
26+
The branching operations specify a number of nesting level they want to exit,
27+
and are redirected to the target of the corresponding nesting LabelLevelOp.
28+
29+
As multiple level can be escaped at once, the level defining ops need themselves
30+
to be `Terminator` ops.
31+
}];
32+
let methods = [
33+
InterfaceMethod<
34+
/*desc=*/ "Returns the target block address",
35+
/*returnType=*/ "::mlir::Block*",
36+
/*methodName=*/ "getLabelTarget",
37+
/*args=*/ (ins)
38+
>
39+
];
40+
41+
let verify = [{
42+
return success(
43+
succeeded(verifyLabelLevelInterfaceIsTerminator<ConcreteOp>()) &&
44+
succeeded(verifyLabelLevelInterface($_op)));
45+
}];
46+
}
47+
48+
def LabelBranchingOpInterface : OpInterface<"LabelBranchingOpInterface"> {
49+
let cppNamespace = "::mlir::wasmssa";
50+
let description = [{
51+
Wasm operation that targets a label for a jump.
52+
}];
53+
let methods = [
54+
InterfaceMethod<
55+
/*desc=*/ "Returns the number of context to break from",
56+
/*returnType=*/ "size_t",
57+
/*methodName=*/ "getExitLevel",
58+
/*args=*/ (ins)
59+
>,
60+
InterfaceMethod<
61+
/*desc=*/ "Returns the destination of this operation",
62+
/*returnType=*/ "LabelLevelOpInterface",
63+
/*methodName=*/ "getTargetOp",
64+
/*args=*/ (ins),
65+
/*methodBody=*/ [{
66+
return *LabelBranchingOpInterface::getTargetOpFromBlock($_op.getOperation()->getBlock(), $_op.getExitLevel());
67+
}]
68+
>,
69+
InterfaceMethod<
70+
/*desc=*/ "Return the target control flow ops that defined the label of this operation",
71+
/*returnType=*/ "::mlir::Block*",
72+
/*methodName=*/ "getTarget",
73+
/*args=*/ (ins),
74+
/*methodBody=*/ [{}],
75+
/*defaultImpl=*/ [{
76+
auto op = mlir::cast<LabelBranchingOpInterface>(this->getOperation());
77+
return op.getTargetOp().getLabelTarget();
78+
}]
79+
>
80+
];
81+
82+
let extraClassDeclaration = [{
83+
static ::llvm::FailureOr<LabelLevelOpInterface> getTargetOpFromBlock(::mlir::Block *block, uint32_t level);
84+
}];
85+
let verify = [{return verifyLabelBranchingOpInterface($_op);}];
86+
}
87+
88+
def ImportOpInterface : OpInterface<"ImportOpInterface"> {
89+
let cppNamespace = "::mlir::wasmssa";
90+
let description = [{
91+
Operation that imports a symbol from an external Wasm module;
92+
}];
93+
94+
let methods = [
95+
InterfaceMethod<
96+
/*desc=*/ "Returns the module name for the import",
97+
/*returnType=*/ "::llvm::StringRef",
98+
/*methodName=*/ "getModuleName",
99+
/*args=*/ (ins)
100+
>,
101+
InterfaceMethod<
102+
/*desc=*/ "Returns the import name for the import",
103+
/*returnType=*/ "::llvm::StringRef",
104+
/*methodName=*/ "getImportName",
105+
/*args=*/ (ins)
106+
>,
107+
InterfaceMethod<
108+
/*desc=*/ "Returns the Wasm index based symbol of the op",
109+
/*returnType=*/ "::mlir::StringAttr",
110+
/*methodName=*/ "getSymbolName",
111+
/*args=*/ (ins),
112+
/*methodBody=*/ [{}],
113+
/*defaultImpl=*/ [{
114+
auto op = mlir::cast<ConcreteOp>(this->getOperation());
115+
return op.getSymNameAttr();
116+
}]
117+
>,
118+
InterfaceMethod<
119+
/*desc=*/ "Returns the qualified name of the import",
120+
/*returnType=*/ "std::string",
121+
/*methodName=*/ "getQualifiedImportName",
122+
/*args=*/ (ins),
123+
/*methodBody=*/ [{
124+
return ($_op.getModuleName() + ::llvm::Twine{"::"} + $_op.getImportName()).str();
125+
}]
126+
>,
127+
];
128+
}
129+
130+
def ConstantExpressionInitializerOpTrait : NativeOpTrait<"ConstantExpressionInitializerOpTrait"> {
131+
let cppNamespace = "::mlir::wasmssa";
132+
}
133+
134+
def ConstantExprOpTrait : NativeOpTrait<"ConstantExprOpTrait"> {
135+
let cppNamespace = "::mlir::wasmssa";
136+
}
137+
138+
#endif // WEBASSEMBLY_INTERFACES

0 commit comments

Comments
 (0)