[Mlir-commits] [mlir] [mlir][wasmssa] Fix if/else round-trip and verify return types (PR #227828)
Ferdinand Lemaire
llvmlistbot at llvm.org
Sat Oct 3 19:42:44 PDT 2026
https://github.com/flemairen6 updated https://github.com/llvm/llvm-project/pull/227828
>From a52cafc0cc096953ce492d92a1777f88261d3f58 Mon Sep 17 00:00:00 2001
From: Saqib Khan <11544614+saqibkh at users.noreply.github.com>
Date: Wed, 30 Sep 2026 12:41:48 -0500
Subject: [PATCH] [mlir][wasmssa] Fix if/else round-trip and verify return
types
`wasmssa.if` printed its else keyword with printKeywordOrString("else "),
which emits the quoted string "else " because of the trailing space.
The parser only accepts the `else` keyword, so printed IR with an else
region failed to parse back (#226072). Print the keyword directly.
`wasmssa.return` had no verifier, so a function could return values
whose number or types differ from its declared results (#226073). Add a
verifier that checks the operands against the enclosing `wasmssa.func`,
which also covers returns nested in block, loop and if regions.
Update the tests that captured the broken `"else "` output, fix
`@func_0` in custom_parser/if.mlir, which returned f32 from an i32
function, and run it through a print/parse round trip.
Fixes #226072
Fixes #226073
Assisted-by: Claude Code (Claude Opus 5.5)
---
.../mlir/Dialect/WasmSSA/IR/WasmSSAOps.td | 1 +
mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp | 20 ++++++++++-
.../Dialect/WasmSSA/custom_parser/if.mlir | 7 ++--
mlir/test/Dialect/WasmSSA/return-invalid.mlir | 36 +++++++++++++++++++
mlir/test/Target/Wasm/if.mlir | 4 +--
5 files changed, 62 insertions(+), 6 deletions(-)
create mode 100644 mlir/test/Dialect/WasmSSA/return-invalid.mlir
diff --git a/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td b/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td
index 2df567c393e59..050877fb78507 100644
--- a/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td
+++ b/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td
@@ -685,6 +685,7 @@ def WasmSSA_ReturnOp : WasmSSA_Op<"return", [Terminator]> {
let builders = [
OpBuilder<(ins)>
];
+ let hasVerifier = 1;
}
def WasmSSA_SelectOp : WasmSSA_Op<"select", [
diff --git a/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp b/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp
index e0e4b085bc21e..e04201863b107 100644
--- a/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp
+++ b/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp
@@ -37,7 +37,7 @@ void printElseRegion(OpAsmPrinter &opPrinter, Operation *op,
Region &elseRegion) {
if (elseRegion.empty())
return;
- opPrinter.printKeywordOrString("else ");
+ opPrinter << "else ";
opPrinter.printRegion(elseRegion);
}
} // namespace
@@ -493,3 +493,21 @@ LogicalResult ReinterpretOp::verify() {
//===----------------------------------------------------------------------===//
void ReturnOp::build(OpBuilder &odsBuilder, OperationState &odsState) {}
+
+LogicalResult ReturnOp::verify() {
+ auto funcOp = (*this)->getParentOfType<FuncOp>();
+ if (!funcOp)
+ return success();
+ ArrayRef<Type> resultTypes = funcOp.getFunctionType().getResults();
+ if (getOperands().size() != resultTypes.size())
+ return emitOpError("has ") << getOperands().size()
+ << " operands, but enclosing function returns "
+ << resultTypes.size();
+ for (auto [idx, resultType, operandType] :
+ llvm::enumerate(resultTypes, getOperands().getTypes()))
+ if (resultType != operandType)
+ return emitOpError("type of return operand #")
+ << idx << " (" << operandType
+ << ") doesn't match function result type (" << resultType << ")";
+ return success();
+}
diff --git a/mlir/test/Dialect/WasmSSA/custom_parser/if.mlir b/mlir/test/Dialect/WasmSSA/custom_parser/if.mlir
index cee3c695af2f0..e0f39651a5728 100644
--- a/mlir/test/Dialect/WasmSSA/custom_parser/if.mlir
+++ b/mlir/test/Dialect/WasmSSA/custom_parser/if.mlir
@@ -1,18 +1,19 @@
// RUN: mlir-opt %s | FileCheck %s
+// RUN: mlir-opt %s | mlir-opt | FileCheck %s
// CHECK-LABEL: wasmssa.func @func_0(
-// CHECK-SAME: %[[ARG0:.*]]: !wasmssa<local ref to i32>) -> i32 {
+// CHECK-SAME: %[[ARG0:.*]]: !wasmssa<local ref to i32>) -> f32 {
// CHECK: %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: wasmssa.if %[[VAL_0]] : {
// CHECK: %[[VAL_1:.*]] = wasmssa.const 5.000000e-01 : f32
// CHECK: wasmssa.block_return %[[VAL_1]] : f32
-// CHECK: } "else "{
+// CHECK: } else {
// CHECK: %[[VAL_2:.*]] = wasmssa.const 2.500000e-01 : f32
// CHECK: wasmssa.block_return %[[VAL_2]] : f32
// CHECK: }> ^bb1
// CHECK: ^bb1(%[[VAL_3:.*]]: f32):
// CHECK: wasmssa.return %[[VAL_3]] : f32
-wasmssa.func @func_0(%arg0 : !wasmssa<local ref to i32>) -> i32 {
+wasmssa.func @func_0(%arg0 : !wasmssa<local ref to i32>) -> f32 {
%cond = wasmssa.local_get %arg0 : ref to i32
wasmssa.if %cond : {
%c0 = wasmssa.const 0.5 : f32
diff --git a/mlir/test/Dialect/WasmSSA/return-invalid.mlir b/mlir/test/Dialect/WasmSSA/return-invalid.mlir
new file mode 100644
index 0000000000000..6d0c673ce35a8
--- /dev/null
+++ b/mlir/test/Dialect/WasmSSA/return-invalid.mlir
@@ -0,0 +1,36 @@
+// RUN: mlir-opt %s -split-input-file -verify-diagnostics
+
+wasmssa.func @return_type_mismatch() -> i32 {
+ %0 = wasmssa.const 0.5 : f32
+ // expected-error at +1 {{type of return operand #0 ('f32') doesn't match function result type ('i32')}}
+ wasmssa.return %0 : f32
+}
+
+// -----
+
+wasmssa.func @return_too_few_operands() -> i32 {
+ // expected-error at +1 {{has 0 operands, but enclosing function returns 1}}
+ wasmssa.return
+}
+
+// -----
+
+wasmssa.func @return_too_many_operands() {
+ %0 = wasmssa.const 1 : i32
+ // expected-error at +1 {{has 1 operands, but enclosing function returns 0}}
+ wasmssa.return %0 : i32
+}
+
+// -----
+
+wasmssa.func @return_in_nested_region(%arg0 : !wasmssa<local ref to i32>) -> i64 {
+ %cond = wasmssa.local_get %arg0 : ref to i32
+ wasmssa.if %cond : {
+ %c0 = wasmssa.const 1 : i32
+ // expected-error at +1 {{type of return operand #0 ('i32') doesn't match function result type ('i64')}}
+ wasmssa.return %c0 : i32
+ } >^bb1
+ ^bb1:
+ %c1 = wasmssa.const 2 : i64
+ wasmssa.return %c1 : i64
+}
diff --git a/mlir/test/Target/Wasm/if.mlir b/mlir/test/Target/Wasm/if.mlir
index 2d7bfbed6f754..a7acc3d836e64 100644
--- a/mlir/test/Target/Wasm/if.mlir
+++ b/mlir/test/Target/Wasm/if.mlir
@@ -62,7 +62,7 @@
// CHECK: %[[VAL_6:.*]] = wasmssa.const 1 : i32
// CHECK: %[[VAL_7:.*]] = wasmssa.add %[[VAL_5]] %[[VAL_6]] : i32
// CHECK: wasmssa.block_return %[[VAL_7]] : i32
-// CHECK: } "else "{
+// CHECK: } else {
// CHECK: %[[VAL_8:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: %[[VAL_9:.*]] = wasmssa.const 1 : i32
// CHECK: %[[VAL_10:.*]] = wasmssa.shr_u %[[VAL_8]] by %[[VAL_9]] bits : i32
@@ -104,7 +104,7 @@
// CHECK: } > ^bb1
// CHECK: ^bb1(%[[VAL_10:.*]]: i32):
// CHECK: wasmssa.block_return %[[VAL_10]] : i32
-// CHECK: } "else "{
+// CHECK: } else {
// CHECK: %[[VAL_11:.*]] = wasmssa.const 1 : i32
// CHECK: wasmssa.block_return %[[VAL_11]] : i32
// CHECK: }> ^bb1
More information about the Mlir-commits
mailing list