[Mlir-commits] [mlir] Lforget.wasm importer controlf flow conv comp (PR #154674)

Luc Forget llvmlistbot at llvm.org
Wed Aug 20 22:39:08 PDT 2025


https://github.com/lforg37 created https://github.com/llvm/llvm-project/pull/154674

None

>From d9f4d19b95a33533b29932da740dfab99d9648a2 Mon Sep 17 00:00:00 2001
From: Luc Forget <dev at alias.lforget.fr>
Date: Thu, 3 Jul 2025 01:08:43 +0200
Subject: [PATCH 1/3] [mlir][wasm] Add support for comparison ops in importer

---------

Co-authored-by: Ferdinand Lemaire <ferdinand.lemaire at woven-planet.global>
Co-authored-by: Jessica Paquette <jessica.paquette at woven-planet.global>
---
 .../mlir/Target/Wasm/WasmBinaryEncoding.h     |  36 +++
 mlir/lib/Target/Wasm/TranslateFromWasm.cpp    |  15 +
 mlir/test/Target/Wasm/comparison_ops.mlir     | 269 ++++++++++++++++++
 mlir/test/Target/Wasm/eq.mlir                 |  56 ++++
 mlir/test/Target/Wasm/eqz.mlir                |  21 ++
 .../Wasm/inputs/comparison_ops.yaml.wasm      |  88 ++++++
 mlir/test/Target/Wasm/inputs/eq.yaml.wasm     |  27 ++
 mlir/test/Target/Wasm/inputs/eqz.yaml.wasm    |  29 ++
 mlir/test/Target/Wasm/inputs/ne.yaml.wasm     |  27 ++
 mlir/test/Target/Wasm/ne.mlir                 |  52 ++++
 10 files changed, 620 insertions(+)
 create mode 100644 mlir/test/Target/Wasm/comparison_ops.mlir
 create mode 100644 mlir/test/Target/Wasm/eq.mlir
 create mode 100644 mlir/test/Target/Wasm/eqz.mlir
 create mode 100644 mlir/test/Target/Wasm/inputs/comparison_ops.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/eq.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/eqz.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/ne.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/ne.mlir

diff --git a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
index 21adde878994e..6e255c23b8679 100644
--- a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
+++ b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
@@ -29,6 +29,42 @@ struct WasmBinaryEncoding {
     static constexpr std::byte constFP32{0x43};
     static constexpr std::byte constFP64{0x44};
 
+    // Comparisons.
+    static constexpr std::byte eqzI32{0x45};
+    static constexpr std::byte eqI32{0x46};
+    static constexpr std::byte neI32{0x47};
+    static constexpr std::byte ltSI32{0x48};
+    static constexpr std::byte ltUI32{0x49};
+    static constexpr std::byte gtSI32{0x4A};
+    static constexpr std::byte gtUI32{0x4B};
+    static constexpr std::byte leSI32{0x4C};
+    static constexpr std::byte leUI32{0x4D};
+    static constexpr std::byte geSI32{0x4E};
+    static constexpr std::byte geUI32{0x4F};
+    static constexpr std::byte eqzI64{0x50};
+    static constexpr std::byte eqI64{0x51};
+    static constexpr std::byte neI64{0x52};
+    static constexpr std::byte ltSI64{0x53};
+    static constexpr std::byte ltUI64{0x54};
+    static constexpr std::byte gtSI64{0x55};
+    static constexpr std::byte gtUI64{0x56};
+    static constexpr std::byte leSI64{0x57};
+    static constexpr std::byte leUI64{0x58};
+    static constexpr std::byte geSI64{0x59};
+    static constexpr std::byte geUI64{0x5A};
+    static constexpr std::byte eqF32{0x5B};
+    static constexpr std::byte neF32{0x5C};
+    static constexpr std::byte ltF32{0x5D};
+    static constexpr std::byte gtF32{0x5E};
+    static constexpr std::byte leF32{0x5F};
+    static constexpr std::byte geF32{0x60};
+    static constexpr std::byte eqF64{0x61};
+    static constexpr std::byte neF64{0x62};
+    static constexpr std::byte ltF64{0x63};
+    static constexpr std::byte gtF64{0x64};
+    static constexpr std::byte leF64{0x65};
+    static constexpr std::byte geF64{0x66};
+
     // Numeric operations.
     static constexpr std::byte clzI32{0x67};
     static constexpr std::byte ctzI32{0x68};
diff --git a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
index 6afbe0505e649..7ef7f5c84c943 100644
--- a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
+++ b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
@@ -1000,11 +1000,23 @@ inline parsed_inst_t ExpressionParser::buildNumericOp(
 
 BUILD_NUMERIC_BINOP_FP(CopySignOp, copysign)
 BUILD_NUMERIC_BINOP_FP(DivOp, div)
+BUILD_NUMERIC_BINOP_FP(GeOp, ge)
+BUILD_NUMERIC_BINOP_FP(GtOp, gt)
+BUILD_NUMERIC_BINOP_FP(LeOp, le)
+BUILD_NUMERIC_BINOP_FP(LtOp, lt)
 BUILD_NUMERIC_BINOP_FP(MaxOp, max)
 BUILD_NUMERIC_BINOP_FP(MinOp, min)
 BUILD_NUMERIC_BINOP_INT(AndOp, and)
 BUILD_NUMERIC_BINOP_INT(DivSIOp, divS)
 BUILD_NUMERIC_BINOP_INT(DivUIOp, divU)
+BUILD_NUMERIC_BINOP_INT(GeSIOp, geS)
+BUILD_NUMERIC_BINOP_INT(GeUIOp, geU)
+BUILD_NUMERIC_BINOP_INT(GtSIOp, gtS)
+BUILD_NUMERIC_BINOP_INT(GtUIOp, gtU)
+BUILD_NUMERIC_BINOP_INT(LeSIOp, leS)
+BUILD_NUMERIC_BINOP_INT(LeUIOp, leU)
+BUILD_NUMERIC_BINOP_INT(LtSIOp, ltS)
+BUILD_NUMERIC_BINOP_INT(LtUIOp, ltU)
 BUILD_NUMERIC_BINOP_INT(OrOp, or)
 BUILD_NUMERIC_BINOP_INT(RemSIOp, remS)
 BUILD_NUMERIC_BINOP_INT(RemUIOp, remU)
@@ -1015,7 +1027,9 @@ BUILD_NUMERIC_BINOP_INT(ShRSOp, shrS)
 BUILD_NUMERIC_BINOP_INT(ShRUOp, shrU)
 BUILD_NUMERIC_BINOP_INT(XOrOp, xor)
 BUILD_NUMERIC_BINOP_INTFP(AddOp, add)
+BUILD_NUMERIC_BINOP_INTFP(EqOp, eq)
 BUILD_NUMERIC_BINOP_INTFP(MulOp, mul)
+BUILD_NUMERIC_BINOP_INTFP(NeOp, ne)
 BUILD_NUMERIC_BINOP_INTFP(SubOp, sub)
 BUILD_NUMERIC_UNARY_OP_FP(AbsOp, abs)
 BUILD_NUMERIC_UNARY_OP_FP(CeilOp, ceil)
@@ -1025,6 +1039,7 @@ BUILD_NUMERIC_UNARY_OP_FP(SqrtOp, sqrt)
 BUILD_NUMERIC_UNARY_OP_FP(TruncOp, trunc)
 BUILD_NUMERIC_UNARY_OP_INT(ClzOp, clz)
 BUILD_NUMERIC_UNARY_OP_INT(CtzOp, ctz)
+BUILD_NUMERIC_UNARY_OP_INT(EqzOp, eqz)
 BUILD_NUMERIC_UNARY_OP_INT(PopCntOp, popcnt)
 
 // Don't need these anymore so let's undef them.
diff --git a/mlir/test/Target/Wasm/comparison_ops.mlir b/mlir/test/Target/Wasm/comparison_ops.mlir
new file mode 100644
index 0000000000000..54c96be74d8f1
--- /dev/null
+++ b/mlir/test/Target/Wasm/comparison_ops.mlir
@@ -0,0 +1,269 @@
+// RUN: yaml2obj %S/inputs/comparison_ops.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+/* Source code used to create this test:
+(module
+    (func $lt_si32 (result i32)
+        i32.const 12
+        i32.const 50
+        i32.lt_s
+    )
+    (func $le_si32 (result i32)
+        i32.const 12
+        i32.const 50
+        i32.le_s
+    )
+    (func $lt_ui32 (result i32)
+        i32.const 12
+        i32.const 50
+        i32.lt_u
+    )
+    (func $le_ui32 (result i32)
+        i32.const 12
+        i32.const 50
+        i32.le_u
+    )
+    (func $gt_si32 (result i32)
+        i32.const 12
+        i32.const 50
+        i32.gt_s
+    )
+    (func $gt_ui32 (result i32)
+        i32.const 12
+        i32.const 50
+        i32.gt_u
+    )
+    (func $ge_si32 (result i32)
+        i32.const 12
+        i32.const 50
+        i32.ge_s
+    )
+    (func $ge_ui32 (result i32)
+        i32.const 12
+        i32.const 50
+        i32.ge_u
+    )
+    (func $lt_si64 (result i32)
+        i64.const 12
+        i64.const 50
+        i64.lt_s
+    )
+    (func $le_si64 (result i32)
+        i64.const 12
+        i64.const 50
+        i64.le_s
+    )
+    (func $lt_ui64 (result i32)
+        i64.const 12
+        i64.const 50
+        i64.lt_u
+    )
+    (func $le_ui64 (result i32)
+        i64.const 12
+        i64.const 50
+        i64.le_u
+    )
+    (func $gt_si64 (result i32)
+        i64.const 12
+        i64.const 50
+        i64.gt_s
+    )
+    (func $gt_ui64 (result i32)
+        i64.const 12
+        i64.const 50
+        i64.gt_u
+    )
+    (func $ge_si64 (result i32)
+        i64.const 12
+        i64.const 50
+        i64.ge_s
+    )
+    (func $ge_ui64 (result i32)
+        i64.const 12
+        i64.const 50
+        i64.ge_u
+    )
+    (func $lt_f32 (result i32)
+        f32.const 5
+        f32.const 14
+        f32.lt
+    )
+    (func $le_f32 (result i32)
+        f32.const 5
+        f32.const 14
+        f32.le
+    )
+    (func $gt_f32 (result i32)
+        f32.const 5
+        f32.const 14
+        f32.gt
+    )
+    (func $ge_f32 (result i32)
+        f32.const 5
+        f32.const 14
+        f32.ge
+    )
+    (func $lt_f64 (result i32)
+        f64.const 5
+        f64.const 14
+        f64.lt
+    )
+    (func $le_f64 (result i32)
+        f64.const 5
+        f64.const 14
+        f64.le
+    )
+    (func $gt_f64 (result i32)
+        f64.const 5
+        f64.const 14
+        f64.gt
+    )
+    (func $ge_f64 (result i32)
+        f64.const 5
+        f64.const 14
+        f64.ge
+    )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.lt_si %[[VAL_0]] %[[VAL_1]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_1() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.le_si %[[VAL_0]] %[[VAL_1]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_2() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.lt_ui %[[VAL_0]] %[[VAL_1]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_3() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.le_ui %[[VAL_0]] %[[VAL_1]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_4() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.gt_si %[[VAL_0]] %[[VAL_1]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_5() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.gt_ui %[[VAL_0]] %[[VAL_1]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_6() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.ge_si %[[VAL_0]] %[[VAL_1]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_7() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.ge_ui %[[VAL_0]] %[[VAL_1]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_8() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.lt_si %[[VAL_0]] %[[VAL_1]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_9() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.le_si %[[VAL_0]] %[[VAL_1]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_10() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.lt_ui %[[VAL_0]] %[[VAL_1]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_11() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.le_ui %[[VAL_0]] %[[VAL_1]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_12() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.gt_si %[[VAL_0]] %[[VAL_1]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_13() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.gt_ui %[[VAL_0]] %[[VAL_1]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_14() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.ge_si %[[VAL_0]] %[[VAL_1]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_15() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.ge_ui %[[VAL_0]] %[[VAL_1]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_16() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.lt %[[VAL_0]] %[[VAL_1]] : f32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_17() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.le %[[VAL_0]] %[[VAL_1]] : f32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_18() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.gt %[[VAL_0]] %[[VAL_1]] : f32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_19() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.ge %[[VAL_0]] %[[VAL_1]] : f32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_20() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.lt %[[VAL_0]] %[[VAL_1]] : f64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_21() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.le %[[VAL_0]] %[[VAL_1]] : f64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_22() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.gt %[[VAL_0]] %[[VAL_1]] : f64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_23() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.ge %[[VAL_0]] %[[VAL_1]] : f64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
diff --git a/mlir/test/Target/Wasm/eq.mlir b/mlir/test/Target/Wasm/eq.mlir
new file mode 100644
index 0000000000000..a78792c6e8110
--- /dev/null
+++ b/mlir/test/Target/Wasm/eq.mlir
@@ -0,0 +1,56 @@
+// RUN: yaml2obj %S/inputs/eq.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+/* Source code used to create this test:
+(module
+    (func $eq_i32 (result i32)
+        i32.const 12
+        i32.const 50
+        i32.eq
+    )
+
+    (func $eq_i64 (result i32)
+        i64.const 20
+        i64.const 5
+        i64.eq
+    )
+
+    (func $eq_f32 (result i32)
+        f32.const 5
+        f32.const 14
+        f32.eq
+    )
+
+    (func $eq_f64 (result i32)
+        f64.const 17
+        f64.const 0
+        f64.eq
+    )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.eq %[[VAL_0]] %[[VAL_1]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+// CHECK:         }
+
+// CHECK-LABEL:   wasmssa.func nested @func_1() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 20 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 5 : i64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.eq %[[VAL_0]] %[[VAL_1]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+// CHECK:         }
+
+// CHECK-LABEL:   wasmssa.func nested @func_2() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.eq %[[VAL_0]] %[[VAL_1]] : f32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+// CHECK:         }
+
+// CHECK-LABEL:   wasmssa.func nested @func_3() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.700000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 0.000000e+00 : f64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.eq %[[VAL_0]] %[[VAL_1]] : f64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+// CHECK:         }
diff --git a/mlir/test/Target/Wasm/eqz.mlir b/mlir/test/Target/Wasm/eqz.mlir
new file mode 100644
index 0000000000000..e4972db1e3a9e
--- /dev/null
+++ b/mlir/test/Target/Wasm/eqz.mlir
@@ -0,0 +1,21 @@
+// RUN: yaml2obj %S/inputs/eqz.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+/* Source code used to create this test:
+(module
+    (func (export "eqz_i32") (result i32)
+    i32.const 13
+    i32.eqz)
+
+    (func (export "eqz_i64") (result i32)
+    i64.const 13
+    i64.eqz)
+)
+*/
+// CHECK-LABEL:   wasmssa.func @eqz_i32() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 13 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.eqz %[[VAL_0]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_1]] : i32
+
+// CHECK-LABEL:   wasmssa.func @eqz_i64() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 13 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.eqz %[[VAL_0]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_1]] : i32
diff --git a/mlir/test/Target/Wasm/inputs/comparison_ops.yaml.wasm b/mlir/test/Target/Wasm/inputs/comparison_ops.yaml.wasm
new file mode 100644
index 0000000000000..cde9ee13e7f1f
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/comparison_ops.yaml.wasm
@@ -0,0 +1,88 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            410C4132480B
+      - Index:           1
+        Locals:          []
+        Body:            410C41324C0B
+      - Index:           2
+        Locals:          []
+        Body:            410C4132490B
+      - Index:           3
+        Locals:          []
+        Body:            410C41324D0B
+      - Index:           4
+        Locals:          []
+        Body:            410C41324A0B
+      - Index:           5
+        Locals:          []
+        Body:            410C41324B0B
+      - Index:           6
+        Locals:          []
+        Body:            410C41324E0B
+      - Index:           7
+        Locals:          []
+        Body:            410C41324F0B
+      - Index:           8
+        Locals:          []
+        Body:            420C4232530B
+      - Index:           9
+        Locals:          []
+        Body:            420C4232570B
+      - Index:           10
+        Locals:          []
+        Body:            420C4232540B
+      - Index:           11
+        Locals:          []
+        Body:            420C4232580B
+      - Index:           12
+        Locals:          []
+        Body:            420C4232550B
+      - Index:           13
+        Locals:          []
+        Body:            420C4232560B
+      - Index:           14
+        Locals:          []
+        Body:            420C4232590B
+      - Index:           15
+        Locals:          []
+        Body:            420C42325A0B
+      - Index:           16
+        Locals:          []
+        Body:            430000A04043000060415D0B
+      - Index:           17
+        Locals:          []
+        Body:            430000A04043000060415F0B
+      - Index:           18
+        Locals:          []
+        Body:            430000A04043000060415E0B
+      - Index:           19
+        Locals:          []
+        Body:            430000A0404300006041600B
+      - Index:           20
+        Locals:          []
+        Body:            440000000000001440440000000000002C40630B
+      - Index:           21
+        Locals:          []
+        Body:            440000000000001440440000000000002C40650B
+      - Index:           22
+        Locals:          []
+        Body:            440000000000001440440000000000002C40640B
+      - Index:           23
+        Locals:          []
+        Body:            440000000000001440440000000000002C40660B
+...
diff --git a/mlir/test/Target/Wasm/inputs/eq.yaml.wasm b/mlir/test/Target/Wasm/inputs/eq.yaml.wasm
new file mode 100644
index 0000000000000..19983695c6854
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/eq.yaml.wasm
@@ -0,0 +1,27 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0, 0, 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            410C4132460B
+      - Index:           1
+        Locals:          []
+        Body:            42144205510B
+      - Index:           2
+        Locals:          []
+        Body:            430000A04043000060415B0B
+      - Index:           3
+        Locals:          []
+        Body:            440000000000003140440000000000000000610B
+...
diff --git a/mlir/test/Target/Wasm/inputs/eqz.yaml.wasm b/mlir/test/Target/Wasm/inputs/eqz.yaml.wasm
new file mode 100644
index 0000000000000..894ac50a8dc97
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/eqz.yaml.wasm
@@ -0,0 +1,29 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0 ]
+  - Type:            EXPORT
+    Exports:
+      - Name:            eqz_i32
+        Kind:            FUNCTION
+        Index:           0
+      - Name:            eqz_i64
+        Kind:            FUNCTION
+        Index:           1
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            410D450B
+      - Index:           1
+        Locals:          []
+        Body:            420D500B
+...
diff --git a/mlir/test/Target/Wasm/inputs/ne.yaml.wasm b/mlir/test/Target/Wasm/inputs/ne.yaml.wasm
new file mode 100644
index 0000000000000..0167519b27459
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/ne.yaml.wasm
@@ -0,0 +1,27 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0, 0, 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            410C4132470B
+      - Index:           1
+        Locals:          []
+        Body:            42144205520B
+      - Index:           2
+        Locals:          []
+        Body:            430000A04043000060415C0B
+      - Index:           3
+        Locals:          []
+        Body:            440000000000003140440000000000000000620B
+...
diff --git a/mlir/test/Target/Wasm/ne.mlir b/mlir/test/Target/Wasm/ne.mlir
new file mode 100644
index 0000000000000..a1268c6da7574
--- /dev/null
+++ b/mlir/test/Target/Wasm/ne.mlir
@@ -0,0 +1,52 @@
+// RUN: yaml2obj %S/inputs/ne.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+/* Source code used to create this test:
+(module
+    (func $ne_i32 (result i32)
+        i32.const 12
+        i32.const 50
+        i32.ne
+    )
+
+    (func $ne_i64 (result i32)
+        i64.const 20
+        i64.const 5
+        i64.ne
+    )
+
+    (func $ne_f32 (result i32)
+        f32.const 5
+        f32.const 14
+        f32.ne
+    )
+
+    (func $ne_f64 (result i32)
+        f64.const 17
+        f64.const 0
+        f64.ne
+    )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 12 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 50 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.ne %[[VAL_0]] %[[VAL_1]] : i32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_1() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 20 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 5 : i64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.ne %[[VAL_0]] %[[VAL_1]] : i64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_2() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.ne %[[VAL_0]] %[[VAL_1]] : f32 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_3() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.700000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 0.000000e+00 : f64
+// CHECK:           %[[VAL_2:.*]] = wasmssa.ne %[[VAL_0]] %[[VAL_1]] : f64 -> i32
+// CHECK:           wasmssa.return %[[VAL_2]] : i32

>From 1504224944d31cfe3bf546eaebe55b56e5a72096 Mon Sep 17 00:00:00 2001
From: Luc Forget <dev at alias.lforget.fr>
Date: Thu, 3 Jul 2025 01:16:19 +0200
Subject: [PATCH 2/3] [mlir][wasm] Support for conversion ops in Wasm importer

---------

Co-authored-by: Ferdinand Lemaire <ferdinand.lemaire at woven-planet.global>
Co-authored-by: Jessica Paquette <jessica.paquette at woven-planet.global>
---
 .../mlir/Target/Wasm/WasmBinaryEncoding.h     |  27 +++++
 mlir/lib/Target/Wasm/TranslateFromWasm.cpp    | 112 ++++++++++++++++++
 mlir/test/Target/Wasm/convert.mlir            |  85 +++++++++++++
 mlir/test/Target/Wasm/demote.mlir             |  15 +++
 mlir/test/Target/Wasm/extend.mlir             |  69 +++++++++++
 .../test/Target/Wasm/inputs/convert.yaml.wasm |  69 +++++++++++
 mlir/test/Target/Wasm/inputs/demote.yaml.wasm |  18 +++
 mlir/test/Target/Wasm/inputs/extend.yaml.wasm |  40 +++++++
 .../test/Target/Wasm/inputs/promote.yaml.wasm |  18 +++
 .../Target/Wasm/inputs/reinterpret.yaml.wasm  |  53 +++++++++
 .../Target/Wasm/inputs/rounding.yaml.wasm     |  37 ++++++
 mlir/test/Target/Wasm/inputs/wrap.yaml.wasm   |  24 ++++
 mlir/test/Target/Wasm/promote.mlir            |  14 +++
 mlir/test/Target/Wasm/reinterpret.mlir        |  46 +++++++
 mlir/test/Target/Wasm/rounding.mlir           |  50 ++++++++
 mlir/test/Target/Wasm/wrap.mlir               |  15 +++
 16 files changed, 692 insertions(+)
 create mode 100644 mlir/test/Target/Wasm/convert.mlir
 create mode 100644 mlir/test/Target/Wasm/demote.mlir
 create mode 100644 mlir/test/Target/Wasm/extend.mlir
 create mode 100644 mlir/test/Target/Wasm/inputs/convert.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/demote.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/extend.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/promote.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/reinterpret.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/rounding.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/wrap.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/promote.mlir
 create mode 100644 mlir/test/Target/Wasm/reinterpret.mlir
 create mode 100644 mlir/test/Target/Wasm/rounding.mlir
 create mode 100644 mlir/test/Target/Wasm/wrap.mlir

diff --git a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
index 6e255c23b8679..9303aca439f54 100644
--- a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
+++ b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
@@ -129,6 +129,33 @@ struct WasmBinaryEncoding {
     static constexpr std::byte maxF64{0xA5};
     static constexpr std::byte copysignF64{0xA6};
     static constexpr std::byte wrap{0xA7};
+
+    // Conversion operations
+    static constexpr std::byte extendS{0xAC};
+    static constexpr std::byte extendU{0xAD};
+    static constexpr std::byte convertSI32F32{0xB2};
+    static constexpr std::byte convertUI32F32{0xB3};
+    static constexpr std::byte convertSI64F32{0xB4};
+    static constexpr std::byte convertUI64F32{0xB5};
+
+    static constexpr std::byte demoteF64ToF32{0xB6};
+
+    static constexpr std::byte convertSI32F64{0xB7};
+    static constexpr std::byte convertUI32F64{0xB8};
+    static constexpr std::byte convertSI64F64{0xB9};
+    static constexpr std::byte convertUI64F64{0xBA};
+
+    static constexpr std::byte promoteF32ToF64{0xBB};
+    static constexpr std::byte reinterpretF32AsI32{0xBC};
+    static constexpr std::byte reinterpretF64AsI64{0xBD};
+    static constexpr std::byte reinterpretI32AsF32{0xBE};
+    static constexpr std::byte reinterpretI64AsF64{0xBF};
+
+    static constexpr std::byte extendI328S{0xC0};
+    static constexpr std::byte extendI3216S{0xC1};
+    static constexpr std::byte extendI648S{0xC2};
+    static constexpr std::byte extendI6416S{0xC3};
+    static constexpr std::byte extendI6432S{0xC4};
   };
 
   /// Byte encodings of types in Wasm binaries
diff --git a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
index 7ef7f5c84c943..fff26d98e6131 100644
--- a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
+++ b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
@@ -248,6 +248,19 @@ class ExpressionParser {
   buildNumericOp(OpBuilder &builder,
                  std::enable_if_t<std::is_arithmetic_v<valueType>> * = nullptr);
 
+  /// Construct a conversion operation of type \p opType that takes a value from
+  /// type \p inputType on the stack and will produce a value of type
+  /// \p outputType.
+  ///
+  /// \p opType - The WASM dialect operation to build.
+  /// \p inputType - The operand type for the built instruction.
+  /// \p outputType - The result type for the built instruction.
+  ///
+  /// \returns The parsed instruction result, or failure.
+  template <typename opType, typename inputType, typename outputType,
+            typename... extraArgsT>
+  inline parsed_inst_t buildConvertOp(OpBuilder &builder, extraArgsT...);
+
   /// This function generates a dispatch tree to associate an opcode with a
   /// parser. Parsers are registered by specialising the
   /// `parseSpecificInstruction` function for the op code to handle.
@@ -1051,6 +1064,105 @@ BUILD_NUMERIC_UNARY_OP_INT(PopCntOp, popcnt)
 #undef BUILD_NUMERIC_OP
 #undef BUILD_NUMERIC_CAST_OP
 
+template <typename opType, typename inputType, typename outputType,
+          typename... extraArgsT>
+inline parsed_inst_t ExpressionParser::buildConvertOp(OpBuilder &builder,
+                                                      extraArgsT... extraArgs) {
+  static_assert(std::is_arithmetic_v<inputType>,
+                "InputType should be an arithmetic type");
+  static_assert(std::is_arithmetic_v<outputType>,
+                "OutputType should be an arithmetic type");
+  auto intype = buildLiteralType<inputType>(builder);
+  auto outType = buildLiteralType<outputType>(builder);
+  auto operand = popOperands(intype);
+  if (failed(operand))
+    return failure();
+  auto op = builder.create<opType>(*currentOpLoc, outType, operand->front(),
+                                   extraArgs...);
+  LLVM_DEBUG(llvm::dbgs() << "Built: " << op);
+  return {{op.getResult()}};
+}
+
+template <>
+inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
+    WasmBinaryEncoding::OpCode::demoteF64ToF32>(OpBuilder &builder) {
+  return buildConvertOp<DemoteOp, double, float>(builder);
+}
+
+template <>
+inline parsed_inst_t
+ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::wrap>(
+    OpBuilder &builder) {
+  return buildConvertOp<WrapOp, int64_t, int32_t>(builder);
+}
+
+#define BUILD_CONVERSION_OP(IN_T, OUT_T, SOURCE_OP, TARGET_OP)                 \
+  template <>                                                                  \
+  inline parsed_inst_t ExpressionParser::parseSpecificInstruction<             \
+      WasmBinaryEncoding::OpCode::SOURCE_OP>(OpBuilder & builder) {            \
+    return buildConvertOp<TARGET_OP, IN_T, OUT_T>(builder);                    \
+  }
+
+#define BUILD_CONVERT_OP_FOR(DEST_T, WIDTH)                                    \
+  BUILD_CONVERSION_OP(uint32_t, DEST_T, convertUI32F##WIDTH, ConvertUOp)       \
+  BUILD_CONVERSION_OP(int32_t, DEST_T, convertSI32F##WIDTH, ConvertSOp)        \
+  BUILD_CONVERSION_OP(uint64_t, DEST_T, convertUI64F##WIDTH, ConvertUOp)       \
+  BUILD_CONVERSION_OP(int64_t, DEST_T, convertSI64F##WIDTH, ConvertSOp)
+
+BUILD_CONVERT_OP_FOR(float, 32)
+BUILD_CONVERT_OP_FOR(double, 64)
+
+#undef BUILD_CONVERT_OP_FOR
+
+BUILD_CONVERSION_OP(int32_t, int64_t, extendS, ExtendSI32Op)
+BUILD_CONVERSION_OP(int32_t, int64_t, extendU, ExtendUI32Op)
+
+#undef BUILD_CONVERSION_OP
+
+#define BUILD_SLICE_EXTEND_PARSER(IT_WIDTH, EXTRACT_WIDTH)                     \
+  template <>                                                                  \
+  parsed_inst_t ExpressionParser::parseSpecificInstruction<                    \
+      WasmBinaryEncoding::OpCode::extendI##IT_WIDTH##EXTRACT_WIDTH##S>(        \
+      OpBuilder & builder) {                                                   \
+    using inout_t = int##IT_WIDTH##_t;                                         \
+    auto attr = builder.getUI32IntegerAttr(EXTRACT_WIDTH);                     \
+    return buildConvertOp<ExtendLowBitsSOp, inout_t, inout_t>(builder, attr);  \
+  }
+
+BUILD_SLICE_EXTEND_PARSER(32, 8)
+BUILD_SLICE_EXTEND_PARSER(32, 16)
+BUILD_SLICE_EXTEND_PARSER(64, 8)
+BUILD_SLICE_EXTEND_PARSER(64, 16)
+BUILD_SLICE_EXTEND_PARSER(64, 32)
+
+#undef BUILD_SLICE_EXTEND_PARSER
+
+template <>
+inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
+    WasmBinaryEncoding::OpCode::promoteF32ToF64>(OpBuilder &builder) {
+  return buildConvertOp<PromoteOp, float, double>(builder);
+}
+
+#define BUILD_REINTERPRET_PARSER(WIDTH, FP_TYPE)                               \
+  template <>                                                                  \
+  inline parsed_inst_t ExpressionParser::parseSpecificInstruction<             \
+      WasmBinaryEncoding::OpCode::reinterpretF##WIDTH##AsI##WIDTH>(OpBuilder & \
+                                                                   builder) {  \
+    return buildConvertOp<ReinterpretOp, FP_TYPE, int##WIDTH##_t>(builder);    \
+  }                                                                            \
+                                                                               \
+  template <>                                                                  \
+  inline parsed_inst_t ExpressionParser::parseSpecificInstruction<             \
+      WasmBinaryEncoding::OpCode::reinterpretI##WIDTH##AsF##WIDTH>(OpBuilder & \
+                                                                   builder) {  \
+    return buildConvertOp<ReinterpretOp, int##WIDTH##_t, FP_TYPE>(builder);    \
+  }
+
+BUILD_REINTERPRET_PARSER(32, float)
+BUILD_REINTERPRET_PARSER(64, double)
+
+#undef BUILD_REINTERPRET_PARSER
+
 class WasmBinaryParser {
 private:
   struct SectionRegistry {
diff --git a/mlir/test/Target/Wasm/convert.mlir b/mlir/test/Target/Wasm/convert.mlir
new file mode 100644
index 0000000000000..8ecb0d117942e
--- /dev/null
+++ b/mlir/test/Target/Wasm/convert.mlir
@@ -0,0 +1,85 @@
+// RUN: yaml2obj %S/inputs/convert.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to generate this test:
+(module
+    (func (export "convert_i32_u_to_f32") (result f32)
+    i32.const 10
+    f32.convert_i32_u
+    )
+
+    (func (export "convert_i32_s_to_f32") (result f32)
+    i32.const 42
+    f32.convert_i32_s
+    )
+
+    (func (export "convert_i64_u_to_f32") (result f32)
+    i64.const 17
+    f32.convert_i64_u
+    )
+
+    (func (export "convert_i64s_to_f32") (result f32)
+    i64.const 10
+    f32.convert_i64_s
+    )
+
+    (func (export "convert_i32_u_to_f64") (result f64)
+    i32.const 10
+    f64.convert_i32_u
+    )
+
+    (func (export "convert_i32_s_to_f64") (result f64)
+    i32.const 42
+    f64.convert_i32_s
+    )
+
+    (func (export "convert_i64_u_to_f64") (result f64)
+    i64.const 17
+    f64.convert_i64_u
+    )
+
+    (func (export "convert_i64s_to_f64") (result f64)
+    i64.const 10
+    f64.convert_i64_s
+    )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func @convert_i32_u_to_f32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.convert_u %[[VAL_0]] : i32 to f32
+// CHECK:           wasmssa.return %[[VAL_1]] : f32
+
+// CHECK-LABEL:   wasmssa.func @convert_i32_s_to_f32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 42 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.convert_s %[[VAL_0]] : i32 to f32
+// CHECK:           wasmssa.return %[[VAL_1]] : f32
+
+// CHECK-LABEL:   wasmssa.func @convert_i64_u_to_f32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 17 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.convert_u %[[VAL_0]] : i64 to f32
+// CHECK:           wasmssa.return %[[VAL_1]] : f32
+
+// CHECK-LABEL:   wasmssa.func @convert_i64s_to_f32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.convert_s %[[VAL_0]] : i64 to f32
+// CHECK:           wasmssa.return %[[VAL_1]] : f32
+
+// CHECK-LABEL:   wasmssa.func @convert_i32_u_to_f64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.convert_u %[[VAL_0]] : i32 to f64
+// CHECK:           wasmssa.return %[[VAL_1]] : f64
+
+// CHECK-LABEL:   wasmssa.func @convert_i32_s_to_f64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 42 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.convert_s %[[VAL_0]] : i32 to f64
+// CHECK:           wasmssa.return %[[VAL_1]] : f64
+
+// CHECK-LABEL:   wasmssa.func @convert_i64_u_to_f64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 17 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.convert_u %[[VAL_0]] : i64 to f64
+// CHECK:           wasmssa.return %[[VAL_1]] : f64
+
+// CHECK-LABEL:   wasmssa.func @convert_i64s_to_f64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.convert_s %[[VAL_0]] : i64 to f64
+// CHECK:           wasmssa.return %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/demote.mlir b/mlir/test/Target/Wasm/demote.mlir
new file mode 100644
index 0000000000000..582d9844463b3
--- /dev/null
+++ b/mlir/test/Target/Wasm/demote.mlir
@@ -0,0 +1,15 @@
+// RUN: yaml2obj %S/inputs/demote.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to create this test:
+(module
+  (func $main (result f32)
+    f64.const 2.24
+    f32.demote_f64
+    )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 2.240000e+00 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.demote %[[VAL_0]] : f64 to f32
+// CHECK:           wasmssa.return %[[VAL_1]] : f32
diff --git a/mlir/test/Target/Wasm/extend.mlir b/mlir/test/Target/Wasm/extend.mlir
new file mode 100644
index 0000000000000..b6d3696030007
--- /dev/null
+++ b/mlir/test/Target/Wasm/extend.mlir
@@ -0,0 +1,69 @@
+// RUN: yaml2obj %S/inputs/extend.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to create this test:
+(module
+  (func $i32_s (result i64)
+    i32.const 10
+    i64.extend_i32_s
+  )
+  (func $i32_u (result i64)
+    i32.const 10
+    i64.extend_i32_u
+  )
+  (func $extend8_32 (result i32)
+    i32.const 10
+    i32.extend8_s
+  )
+  (func $extend16_32 (result i32)
+    i32.const 10
+    i32.extend16_s
+  )
+  (func $extend8_64 (result i64)
+    i64.const 10
+    i64.extend8_s
+  )
+  (func $extend16_64 (result i64)
+    i64.const 10
+    i64.extend16_s
+  )
+  (func $extend32_64 (result i64)
+    i64.const 10
+    i64.extend32_s
+  )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.extend_i32_s %[[VAL_0]] to i64
+// CHECK:           wasmssa.return %[[VAL_1]] : i64
+
+// CHECK-LABEL:   wasmssa.func nested @func_1() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.extend_i32_u %[[VAL_0]] to i64
+// CHECK:           wasmssa.return %[[VAL_1]] : i64
+
+// CHECK-LABEL:   wasmssa.func nested @func_2() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.extend 8 : ui32 low bits from %[[VAL_0]] : i32
+// CHECK:           wasmssa.return %[[VAL_1]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_3() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.extend 16 : ui32 low bits from %[[VAL_0]] : i32
+// CHECK:           wasmssa.return %[[VAL_1]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_4() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.extend 8 : ui32 low bits from %[[VAL_0]] : i64
+// CHECK:           wasmssa.return %[[VAL_1]] : i64
+
+// CHECK-LABEL:   wasmssa.func nested @func_5() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.extend 16 : ui32 low bits from %[[VAL_0]] : i64
+// CHECK:           wasmssa.return %[[VAL_1]] : i64
+
+// CHECK-LABEL:   wasmssa.func nested @func_6() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.extend 32 : ui32 low bits from %[[VAL_0]] : i64
+// CHECK:           wasmssa.return %[[VAL_1]] : i64
diff --git a/mlir/test/Target/Wasm/inputs/convert.yaml.wasm b/mlir/test/Target/Wasm/inputs/convert.yaml.wasm
new file mode 100644
index 0000000000000..c346a751bf93a
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/convert.yaml.wasm
@@ -0,0 +1,69 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - F32
+      - Index:           1
+        ParamTypes:      []
+        ReturnTypes:
+          - F64
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0, 0, 0, 1, 1, 1, 1 ]
+  - Type:            EXPORT
+    Exports:
+      - Name:            convert_i32_u_to_f32
+        Kind:            FUNCTION
+        Index:           0
+      - Name:            convert_i32_s_to_f32
+        Kind:            FUNCTION
+        Index:           1
+      - Name:            convert_i64_u_to_f32
+        Kind:            FUNCTION
+        Index:           2
+      - Name:            convert_i64s_to_f32
+        Kind:            FUNCTION
+        Index:           3
+      - Name:            convert_i32_u_to_f64
+        Kind:            FUNCTION
+        Index:           4
+      - Name:            convert_i32_s_to_f64
+        Kind:            FUNCTION
+        Index:           5
+      - Name:            convert_i64_u_to_f64
+        Kind:            FUNCTION
+        Index:           6
+      - Name:            convert_i64s_to_f64
+        Kind:            FUNCTION
+        Index:           7
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            410AB30B
+      - Index:           1
+        Locals:          []
+        Body:            412AB20B
+      - Index:           2
+        Locals:          []
+        Body:            4211B50B
+      - Index:           3
+        Locals:          []
+        Body:            420AB40B
+      - Index:           4
+        Locals:          []
+        Body:            410AB80B
+      - Index:           5
+        Locals:          []
+        Body:            412AB70B
+      - Index:           6
+        Locals:          []
+        Body:            4211BA0B
+      - Index:           7
+        Locals:          []
+        Body:            420AB90B
+...
diff --git a/mlir/test/Target/Wasm/inputs/demote.yaml.wasm b/mlir/test/Target/Wasm/inputs/demote.yaml.wasm
new file mode 100644
index 0000000000000..3997045cd8315
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/demote.yaml.wasm
@@ -0,0 +1,18 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - F32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            44EC51B81E85EB0140B60B
+...
diff --git a/mlir/test/Target/Wasm/inputs/extend.yaml.wasm b/mlir/test/Target/Wasm/inputs/extend.yaml.wasm
new file mode 100644
index 0000000000000..7e872ba0b8296
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/extend.yaml.wasm
@@ -0,0 +1,40 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I64
+      - Index:           1
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0, 1, 1, 0, 0, 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            410AAC0B
+      - Index:           1
+        Locals:          []
+        Body:            410AAD0B
+      - Index:           2
+        Locals:          []
+        Body:            410AC00B
+      - Index:           3
+        Locals:          []
+        Body:            410AC10B
+      - Index:           4
+        Locals:          []
+        Body:            420AC20B
+      - Index:           5
+        Locals:          []
+        Body:            420AC30B
+      - Index:           6
+        Locals:          []
+        Body:            420AC40B
+...
diff --git a/mlir/test/Target/Wasm/inputs/promote.yaml.wasm b/mlir/test/Target/Wasm/inputs/promote.yaml.wasm
new file mode 100644
index 0000000000000..d38603e65deda
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/promote.yaml.wasm
@@ -0,0 +1,18 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - F64
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            4300002841BB0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/reinterpret.yaml.wasm b/mlir/test/Target/Wasm/inputs/reinterpret.yaml.wasm
new file mode 100644
index 0000000000000..c01c1b10c3109
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/reinterpret.yaml.wasm
@@ -0,0 +1,53 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+      - Index:           1
+        ParamTypes:      []
+        ReturnTypes:
+          - I64
+      - Index:           2
+        ParamTypes:      []
+        ReturnTypes:
+          - F32
+      - Index:           3
+        ParamTypes:      []
+        ReturnTypes:
+          - F64
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 1, 2, 3 ]
+  - Type:            EXPORT
+    Exports:
+      - Name:            i32.reinterpret_f32
+        Kind:            FUNCTION
+        Index:           0
+      - Name:            i64.reinterpret_f64
+        Kind:            FUNCTION
+        Index:           1
+      - Name:            f32.reinterpret_i32
+        Kind:            FUNCTION
+        Index:           2
+      - Name:            f64.reinterpret_i64
+        Kind:            FUNCTION
+        Index:           3
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            43000080BFBC0B
+      - Index:           1
+        Locals:          []
+        Body:            44000000000000F0BFBD0B
+      - Index:           2
+        Locals:          []
+        Body:            417FBE0B
+      - Index:           3
+        Locals:          []
+        Body:            427FBF0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/rounding.yaml.wasm b/mlir/test/Target/Wasm/inputs/rounding.yaml.wasm
new file mode 100644
index 0000000000000..c6e8bf6d24f96
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/rounding.yaml.wasm
@@ -0,0 +1,37 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - F64
+      - Index:           1
+        ParamTypes:      []
+        ReturnTypes:
+          - F32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 1, 0, 1, 0, 1 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            4433333333333328C09B0B
+      - Index:           1
+        Locals:          []
+        Body:            43A01ACF3F8D0B
+      - Index:           2
+        Locals:          []
+        Body:            4433333333333328C09C0B
+      - Index:           3
+        Locals:          []
+        Body:            43A01ACF3F8E0B
+      - Index:           4
+        Locals:          []
+        Body:            4433333333333328C09D0B
+      - Index:           5
+        Locals:          []
+        Body:            43A01ACF3F8F0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/wrap.yaml.wasm b/mlir/test/Target/Wasm/inputs/wrap.yaml.wasm
new file mode 100644
index 0000000000000..51c0b027e7158
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/wrap.yaml.wasm
@@ -0,0 +1,24 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:
+          - I64
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0 ]
+  - Type:            EXPORT
+    Exports:
+      - Name:            i64_wrap
+        Kind:            FUNCTION
+        Index:           0
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            2000A70B
+...
diff --git a/mlir/test/Target/Wasm/promote.mlir b/mlir/test/Target/Wasm/promote.mlir
new file mode 100644
index 0000000000000..5e3dca6f568f2
--- /dev/null
+++ b/mlir/test/Target/Wasm/promote.mlir
@@ -0,0 +1,14 @@
+// RUN: yaml2obj %S/inputs/promote.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to generate this test:
+(module
+  (func $main (result f64)
+    f32.const 10.5
+    f64.promote_f32
+  )
+)*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.050000e+01 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.promote %[[VAL_0]] : f32 to f64
+// CHECK:           wasmssa.return %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/reinterpret.mlir b/mlir/test/Target/Wasm/reinterpret.mlir
new file mode 100644
index 0000000000000..7528ebc700401
--- /dev/null
+++ b/mlir/test/Target/Wasm/reinterpret.mlir
@@ -0,0 +1,46 @@
+// RUN: yaml2obj %S/inputs/reinterpret.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/*
+Test generated from:
+(module
+    (func (export "i32.reinterpret_f32") (result i32)
+        f32.const -1
+        i32.reinterpret_f32
+    )
+
+    (func (export "i64.reinterpret_f64") (result i64)
+        f64.const -1
+        i64.reinterpret_f64
+    )
+
+    (func (export "f32.reinterpret_i32") (result f32)
+        i32.const -1
+        f32.reinterpret_i32
+    )
+
+    (func (export "f64.reinterpret_i64") (result f64)
+        i64.const -1
+        f64.reinterpret_i64
+    )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func @i32.reinterpret_f32() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const -1.000000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.reinterpret %[[VAL_0]] : f32 as i32
+// CHECK:           wasmssa.return %[[VAL_1]] : i32
+
+// CHECK-LABEL:   wasmssa.func @i64.reinterpret_f64() -> i64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const -1.000000e+00 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.reinterpret %[[VAL_0]] : f64 as i64
+// CHECK:           wasmssa.return %[[VAL_1]] : i64
+
+// CHECK-LABEL:   wasmssa.func @f32.reinterpret_i32() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const -1 : i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.reinterpret %[[VAL_0]] : i32 as f32
+// CHECK:           wasmssa.return %[[VAL_1]] : f32
+
+// CHECK-LABEL:   wasmssa.func @f64.reinterpret_i64() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const -1 : i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.reinterpret %[[VAL_0]] : i64 as f64
+// CHECK:           wasmssa.return %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/rounding.mlir b/mlir/test/Target/Wasm/rounding.mlir
new file mode 100644
index 0000000000000..bc17379ec1855
--- /dev/null
+++ b/mlir/test/Target/Wasm/rounding.mlir
@@ -0,0 +1,50 @@
+// RUN: yaml2obj %S/inputs/rounding.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+/* Source code used to create this test:
+(module
+  (func $ceil_f64 (result f64)
+    f64.const -12.1
+    f64.ceil
+  )
+  (func $ceil_f32 (result f32)
+    f32.const 1.618
+    f32.ceil
+  )
+  (func $floor_f64 (result f64)
+    f64.const -12.1
+    f64.floor
+  )
+  (func $floor_f32 (result f32)
+    f32.const 1.618
+    f32.floor
+  )
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const -1.210000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.ceil %[[VAL_0]] : f64
+// CHECK:           wasmssa.return %[[VAL_1]] : f64
+
+// CHECK-LABEL:   wasmssa.func nested @func_1() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.618000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.ceil %[[VAL_0]] : f32
+// CHECK:           wasmssa.return %[[VAL_1]] : f32
+
+// CHECK-LABEL:   wasmssa.func nested @func_2() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const -1.210000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.floor %[[VAL_0]] : f64
+// CHECK:           wasmssa.return %[[VAL_1]] : f64
+
+// CHECK-LABEL:   wasmssa.func nested @func_3() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.618000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.floor %[[VAL_0]] : f32
+// CHECK:           wasmssa.return %[[VAL_1]] : f32
+
+// CHECK-LABEL:   wasmssa.func nested @func_4() -> f64 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const -1.210000e+01 : f64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.trunc %[[VAL_0]] : f64
+// CHECK:           wasmssa.return %[[VAL_1]] : f64
+
+// CHECK-LABEL:   wasmssa.func nested @func_5() -> f32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.618000e+00 : f32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.trunc %[[VAL_0]] : f32
+// CHECK:           wasmssa.return %[[VAL_1]] : f32
diff --git a/mlir/test/Target/Wasm/wrap.mlir b/mlir/test/Target/Wasm/wrap.mlir
new file mode 100644
index 0000000000000..86ea0f7609d52
--- /dev/null
+++ b/mlir/test/Target/Wasm/wrap.mlir
@@ -0,0 +1,15 @@
+// RUN: yaml2obj %S/inputs/wrap.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+/* Source code used to create this test:
+(module
+    (func (export "i64_wrap") (param $in i64) (result i32)
+    local.get $in
+    i32.wrap_i64
+    )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func @i64_wrap(
+// CHECK-SAME:      %[[ARG0:.*]]: !wasmssa<local ref to i64>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] :  ref to i64
+// CHECK:           %[[VAL_1:.*]] = wasmssa.wrap %[[VAL_0]] : i64 to i32
+// CHECK:           wasmssa.return %[[VAL_1]] : i32

>From 3f3d3ef310acad90d18135b20b0251b0a48ceb21 Mon Sep 17 00:00:00 2001
From: Luc Forget <dev at alias.lforget.fr>
Date: Thu, 3 Jul 2025 01:27:41 +0200
Subject: [PATCH 3/3] [mlir][wasm] Support for control flow related ops in Wasm
 importer

Add label level tracking system to the importer.
Add import for all the control flow related ops.

---------

Co-authored-by: Ferdinand Lemaire <ferdinand.lemaire at woven-planet.global>
Co-authored-by: Jessica Paquette <jessica.paquette at woven-planet.global>
---
 .../mlir/Target/Wasm/WasmBinaryEncoding.h     |   8 +
 mlir/lib/Target/Wasm/TranslateFromWasm.cpp    | 315 +++++++++++++++++-
 mlir/test/Target/Wasm/abs.mlir                |   4 +-
 mlir/test/Target/Wasm/add_div.mlir            |  40 +++
 mlir/test/Target/Wasm/and.mlir                |   4 +-
 mlir/test/Target/Wasm/block.mlir              |  16 +
 .../test/Target/Wasm/block_complete_type.mlir |  24 ++
 mlir/test/Target/Wasm/block_value_type.mlir   |  19 ++
 mlir/test/Target/Wasm/branch_if.mlir          |  29 ++
 mlir/test/Target/Wasm/call.mlir               |  17 +
 mlir/test/Target/Wasm/clz.mlir                |   4 +-
 mlir/test/Target/Wasm/convert.mlir            |  16 +-
 mlir/test/Target/Wasm/copysign.mlir           |   4 +-
 mlir/test/Target/Wasm/ctz.mlir                |   4 +-
 mlir/test/Target/Wasm/div.mlir                |  20 +-
 mlir/test/Target/Wasm/double_nested_loop.mlir |  63 ++++
 .../Wasm/empty_blocks_list_and_stack.mlir     |  53 +++
 mlir/test/Target/Wasm/eqz.mlir                |   4 +-
 mlir/test/Target/Wasm/if.mlir                 | 112 +++++++
 .../test/Target/Wasm/inputs/add_div.yaml.wasm |  50 +++
 mlir/test/Target/Wasm/inputs/block.yaml.wasm  |  22 ++
 .../Wasm/inputs/block_complete_type.yaml.wasm |  23 ++
 .../Wasm/inputs/block_value_type.yaml.wasm    |  18 +
 .../Target/Wasm/inputs/branch_if.yaml.wasm    |  18 +
 mlir/test/Target/Wasm/inputs/call.yaml.wasm   |  26 ++
 .../Wasm/inputs/double_nested_loop.yaml.wasm  |  19 ++
 .../empty_blocks_list_and_stack.yaml.wasm     |  21 ++
 mlir/test/Target/Wasm/inputs/if.yaml.wasm     |  25 ++
 mlir/test/Target/Wasm/inputs/loop.yaml.wasm   |  17 +
 .../Wasm/inputs/loop_with_inst.yaml.wasm      |  20 ++
 mlir/test/Target/Wasm/loop.mlir               |  17 +
 mlir/test/Target/Wasm/loop_with_inst.mlir     |  33 ++
 mlir/test/Target/Wasm/max.mlir                |   4 +-
 mlir/test/Target/Wasm/min.mlir                |   4 +-
 mlir/test/Target/Wasm/neg.mlir                |   4 +-
 mlir/test/Target/Wasm/or.mlir                 |   4 +-
 mlir/test/Target/Wasm/popcnt.mlir             |   4 +-
 mlir/test/Target/Wasm/reinterpret.mlir        |   8 +-
 mlir/test/Target/Wasm/rem.mlir                |   8 +-
 mlir/test/Target/Wasm/rotl.mlir               |   4 +-
 mlir/test/Target/Wasm/rotr.mlir               |   4 +-
 mlir/test/Target/Wasm/shl.mlir                |   4 +-
 mlir/test/Target/Wasm/shr_s.mlir              |   4 +-
 mlir/test/Target/Wasm/shr_u.mlir              |   4 +-
 mlir/test/Target/Wasm/sqrt.mlir               |   4 +-
 mlir/test/Target/Wasm/wrap.mlir               |   2 +-
 mlir/test/Target/Wasm/xor.mlir                |   4 +-
 47 files changed, 1065 insertions(+), 66 deletions(-)
 create mode 100644 mlir/test/Target/Wasm/add_div.mlir
 create mode 100644 mlir/test/Target/Wasm/block.mlir
 create mode 100644 mlir/test/Target/Wasm/block_complete_type.mlir
 create mode 100644 mlir/test/Target/Wasm/block_value_type.mlir
 create mode 100644 mlir/test/Target/Wasm/branch_if.mlir
 create mode 100644 mlir/test/Target/Wasm/call.mlir
 create mode 100644 mlir/test/Target/Wasm/double_nested_loop.mlir
 create mode 100644 mlir/test/Target/Wasm/empty_blocks_list_and_stack.mlir
 create mode 100644 mlir/test/Target/Wasm/if.mlir
 create mode 100644 mlir/test/Target/Wasm/inputs/add_div.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/block.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/block_complete_type.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/block_value_type.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/branch_if.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/call.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/double_nested_loop.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/empty_blocks_list_and_stack.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/if.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/loop.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/inputs/loop_with_inst.yaml.wasm
 create mode 100644 mlir/test/Target/Wasm/loop.mlir
 create mode 100644 mlir/test/Target/Wasm/loop_with_inst.mlir

diff --git a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
index 9303aca439f54..cd9ef5b2132a4 100644
--- a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
+++ b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
@@ -19,6 +19,14 @@ namespace mlir {
 struct WasmBinaryEncoding {
   /// Byte encodings for Wasm instructions.
   struct OpCode {
+    // Control instructions.
+    static constexpr std::byte block{0x02};
+    static constexpr std::byte loop{0x03};
+    static constexpr std::byte ifOpCode{0x04};
+    static constexpr std::byte elseOpCode{0x05};
+    static constexpr std::byte branchIf{0x0D};
+    static constexpr std::byte call{0x10};
+
     // Locals, globals, constants.
     static constexpr std::byte localGet{0x20};
     static constexpr std::byte localSet{0x21};
diff --git a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
index fff26d98e6131..385acb4a4de65 100644
--- a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
+++ b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
@@ -138,6 +138,10 @@ using ImportDesc =
 
 using parsed_inst_t = FailureOr<SmallVector<Value>>;
 
+struct EmptyBlockMarker {};
+using BlockTypeParseResult =
+    std::variant<EmptyBlockMarker, TypeIdxRecord, Type>;
+
 struct WasmModuleSymbolTables {
   SmallVector<FunctionSymbolRefContainer> funcSymbols;
   SmallVector<GlobalSymbolRefContainer> globalSymbols;
@@ -206,6 +210,16 @@ class ValueStack {
   ///   if an error occurs.
   LogicalResult pushResults(ValueRange results, Location *opLoc);
 
+  void addLabelLevel(LabelLevelOpInterface levelOp) {
+    labelLevel.push_back({values.size(), levelOp});
+    LLVM_DEBUG(llvm::dbgs() << "Adding a new frame context to ValueStack");
+  }
+
+  void dropLabelLevel() {
+    assert(!labelLevel.empty() && "Trying to drop a frame from empty context");
+    auto newSize = labelLevel.pop_back_val().stackIdx;
+    values.truncate(newSize);
+  }
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
   /// A simple dump function for debugging.
   /// Writes output to llvm::dbgs().
@@ -214,6 +228,7 @@ class ValueStack {
 
 private:
   SmallVector<Value> values;
+  SmallVector<LabelLevel> labelLevel;
 };
 
 using local_val_t = TypedValue<wasmssa::LocalRefType>;
@@ -293,11 +308,103 @@ class ExpressionParser {
     }
   }
 
+  struct NestingContext {
+    NestingContext(ExpressionParser &parser, LabelLevelOpInterface levelOp)
+        : parser{parser} {
+      parser.addNestingContextLevel(levelOp);
+    }
+    NestingContext(NestingContext &&other) : parser{other.parser} {
+      other.shouldDropOnDestruct = false;
+    }
+    NestingContext(NestingContext const &) = delete;
+    ~NestingContext() {
+      if (shouldDropOnDestruct)
+        parser.dropNestingContextLevel();
+    }
+    ExpressionParser &parser;
+    bool shouldDropOnDestruct = true;
+  };
+
+  void addNestingContextLevel(LabelLevelOpInterface levelOp) {
+    valueStack.addLabelLevel(levelOp);
+  }
+
+  void dropNestingContextLevel() {
+    // Should always succeed as we are droping the frame that was previously
+    // created.
+    valueStack.dropLabelLevel();
+  }
+
+  llvm::FailureOr<FunctionType> getFuncTypeFor(OpBuilder &builder,
+                                               EmptyBlockMarker) {
+    return builder.getFunctionType({}, {});
+  }
+
+  llvm::FailureOr<FunctionType> getFuncTypeFor(OpBuilder &builder,
+                                               TypeIdxRecord type) {
+    if (type.id > symbols.moduleFuncTypes.size())
+      return emitError(*currentOpLoc,
+                       "Type index references nonexistent type: ")
+             << type.id << ". Only " << symbols.moduleFuncTypes.size()
+             << " types are registered.";
+    return symbols.moduleFuncTypes[type.id];
+  }
+
+  llvm::FailureOr<FunctionType> getFuncTypeFor(OpBuilder &builder,
+                                               Type valType) {
+    return builder.getFunctionType({}, {valType});
+  }
+
+  llvm::FailureOr<FunctionType>
+  getFuncTypeFor(OpBuilder &builder, BlockTypeParseResult parseResult) {
+    return std::visit(
+        [this, &builder](auto value) { return getFuncTypeFor(builder, value); },
+        parseResult);
+  }
+
+  llvm::FailureOr<FunctionType>
+  getFuncTypeFor(OpBuilder &builder,
+                 llvm::FailureOr<BlockTypeParseResult> parseResult) {
+    if (llvm::failed(parseResult))
+      return failure();
+    return getFuncTypeFor(builder, *parseResult);
+  }
+
+  llvm::FailureOr<FunctionType> parseBlockFuncType(OpBuilder &builder);
+
   struct ParseResultWithInfo {
     SmallVector<Value> opResults;
     std::byte endingByte;
   };
 
+  template <typename FilterT = ByteSequence<WasmBinaryEncoding::endByte>>
+  /// @param blockToFill: the block which content will be populated
+  /// @param resType: the type that this block is supposed to return
+  llvm::FailureOr<std::byte>
+  parseBlockContent(OpBuilder &builder, Block *blockToFill, TypeRange resTypes,
+                    Location opLoc, LabelLevelOpInterface levelOp,
+                    FilterT parseEndBytes = {}) {
+    auto sip = builder.saveInsertionPoint();
+    builder.setInsertionPointToStart(blockToFill);
+    LLVM_DEBUG(llvm::dbgs() << "Parsing a block of type "
+                            << builder.getFunctionType(
+                                   blockToFill->getArgumentTypes(), resTypes));
+    auto nC = addNesting(levelOp);
+
+    if (failed(pushResults(blockToFill->getArguments())))
+      return failure();
+    auto bodyParsingRes = parse(builder, parseEndBytes);
+    if (failed(bodyParsingRes))
+      return failure();
+    auto returnOperands = popOperands(resTypes);
+    if (failed(returnOperands))
+      return failure();
+    builder.create<BlockReturnOp>(opLoc, *returnOperands);
+    LLVM_DEBUG(llvm::dbgs() << "End of parsing of a block\n");
+    builder.restoreInsertionPoint(sip);
+    return bodyParsingRes->endingByte;
+  }
+
 public:
   template <std::byte ParseEndByte = WasmBinaryEncoding::endByte>
   parsed_inst_t parse(OpBuilder &builder, UniqueByte<ParseEndByte> = {});
@@ -307,7 +414,11 @@ class ExpressionParser {
   parse(OpBuilder &builder,
         ByteSequence<ExpressionParseEnd...> parsingEndFilters);
 
-  FailureOr<SmallVector<Value>> popOperands(TypeRange operandTypes) {
+  NestingContext addNesting(LabelLevelOpInterface levelOp) {
+    return NestingContext{*this, levelOp};
+  }
+
+  FailureOr<llvm::SmallVector<Value>> popOperands(TypeRange operandTypes) {
     return valueStack.popOperands(operandTypes, &currentOpLoc.value());
   }
 
@@ -321,6 +432,12 @@ class ExpressionParser {
   template <typename OpToCreate>
   parsed_inst_t parseSetOrTee(OpBuilder &);
 
+  /// Blocks and Loops have a similar format and differ only in how their exit
+  /// is handled which doesn´t matter at parsing time. Factorizes in one
+  /// function.
+  template <typename OpToCreate>
+  parsed_inst_t parseBlockLikeOp(OpBuilder &);
+
 private:
   std::optional<Location> currentOpLoc;
   ParserHead &parser;
@@ -599,6 +716,29 @@ class ParserHead {
     return success();
   }
 
+  llvm::FailureOr<BlockTypeParseResult> parseBlockType(MLIRContext *ctx) {
+    auto loc = getLocation();
+    auto blockIndicator = peek();
+    if (failed(blockIndicator))
+      return failure();
+    if (*blockIndicator == WasmBinaryEncoding::Type::emptyBlockType) {
+      offset += 1;
+      return {EmptyBlockMarker{}};
+    }
+    if (isValueOneOf(*blockIndicator, valueTypesEncodings))
+      return parseValueType(ctx);
+    /// Block type idx is a 32 bit positive integer encoded as a 33 bit signed
+    /// value
+    auto typeIdx = parseI64();
+    if (failed(typeIdx))
+      return failure();
+    if (*typeIdx < 0 || *typeIdx > std::numeric_limits<uint32_t>::max())
+      return emitError(loc, "type ID should be representable with an unsigned "
+                            "32 bits integer. Got ")
+             << *typeIdx;
+    return {TypeIdxRecord{static_cast<uint32_t>(*typeIdx)}};
+  }
+
   bool end() const { return curHead().empty(); }
 
   ParserHead copy() const { return *this; }
@@ -714,17 +854,41 @@ inline parsed_inst_t ExpressionParser::parseSpecificInstruction(OpBuilder &) {
 void ValueStack::dump() const {
   llvm::dbgs() << "================= Wasm ValueStack =======================\n";
   llvm::dbgs() << "size: " << size() << "\n";
+  llvm::dbgs() << "nbFrames: " << labelLevel.size() << '\n';
   llvm::dbgs() << "<Top>"
                << "\n";
   // Stack is pushed to via push_back. Therefore the top of the stack is the
   // end of the vector. Iterate in reverse so that the first thing we print
   // is the top of the stack.
+  auto indexGetter = [this]() {
+    size_t idx = labelLevel.size();
+    return [this, idx]() mutable -> std::optional<std::pair<size_t, size_t>> {
+      llvm::dbgs() << "IDX: " << idx << '\n';
+      if (idx == 0)
+        return std::nullopt;
+      auto frameId = idx - 1;
+      auto frameLimit = labelLevel[frameId].stackIdx;
+      idx -= 1;
+      return {{frameId, frameLimit}};
+    };
+  };
+  auto getNextFrameIndex = indexGetter();
+  auto nextFrameIdx = getNextFrameIndex();
   size_t stackSize = size();
-  for (size_t idx = 0; idx < stackSize; idx++) {
+  for (size_t idx = 0; idx < stackSize;) {
     size_t actualIdx = stackSize - 1 - idx;
+    while (nextFrameIdx && (nextFrameIdx->second > actualIdx)) {
+      llvm::dbgs() << "  --------------- Frame (" << nextFrameIdx->first
+                   << ")\n";
+      nextFrameIdx = getNextFrameIndex();
+    }
     llvm::dbgs() << "  ";
     values[actualIdx].dump();
   }
+  while (nextFrameIdx) {
+    llvm::dbgs() << "  --------------- Frame (" << nextFrameIdx->first << ")\n";
+    nextFrameIdx = getNextFrameIndex();
+  }
   llvm::dbgs() << "<Bottom>"
                << "\n";
   llvm::dbgs() << "=========================================================\n";
@@ -805,6 +969,151 @@ ExpressionParser::parse(OpBuilder &builder,
   }
 }
 
+llvm::FailureOr<FunctionType>
+ExpressionParser::parseBlockFuncType(OpBuilder &builder) {
+  return getFuncTypeFor(builder, parser.parseBlockType(builder.getContext()));
+}
+
+template <typename OpToCreate>
+parsed_inst_t ExpressionParser::parseBlockLikeOp(OpBuilder &builder) {
+  auto opLoc = currentOpLoc;
+  auto funcType = parseBlockFuncType(builder);
+  if (failed(funcType))
+    return failure();
+
+  auto inputTypes = funcType->getInputs();
+  auto inputOps = popOperands(inputTypes);
+  if (failed(inputOps))
+    return failure();
+
+  Block *curBlock = builder.getBlock();
+  Region *curRegion = curBlock->getParent();
+  auto resTypes = funcType->getResults();
+  llvm::SmallVector<Location> locations{};
+  locations.resize(resTypes.size(), *currentOpLoc);
+  auto *successor =
+      builder.createBlock(curRegion, curRegion->end(), resTypes, locations);
+  builder.setInsertionPointToEnd(curBlock);
+  auto blockOp =
+      builder.create<OpToCreate>(*currentOpLoc, *inputOps, successor);
+  auto *blockBody = blockOp.createBlock();
+  if (failed(parseBlockContent(builder, blockBody, resTypes, *opLoc, blockOp)))
+    return failure();
+  builder.setInsertionPointToStart(successor);
+  return {ValueRange{successor->getArguments()}};
+}
+
+template <>
+inline parsed_inst_t
+ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::block>(
+    OpBuilder &builder) {
+  return parseBlockLikeOp<BlockOp>(builder);
+}
+
+template <>
+inline parsed_inst_t
+ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::loop>(
+    OpBuilder &builder) {
+  return parseBlockLikeOp<LoopOp>(builder);
+}
+
+template <>
+inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
+    WasmBinaryEncoding::OpCode::ifOpCode>(OpBuilder &builder) {
+  auto opLoc = currentOpLoc;
+  auto funcType = parseBlockFuncType(builder);
+  if (failed(funcType))
+    return failure();
+
+  LLVM_DEBUG(llvm::dbgs() << "Parsing an if instruction of type " << *funcType);
+  auto inputTypes = funcType->getInputs();
+  auto conditionValue = popOperands(builder.getI32Type());
+  if (failed(conditionValue))
+    return failure();
+  auto inputOps = popOperands(inputTypes);
+  if (failed(inputOps))
+    return failure();
+
+  Block *curBlock = builder.getBlock();
+  Region *curRegion = curBlock->getParent();
+  auto resTypes = funcType->getResults();
+  llvm::SmallVector<Location> locations{};
+  locations.resize(resTypes.size(), *currentOpLoc);
+  auto *successor =
+      builder.createBlock(curRegion, curRegion->end(), resTypes, locations);
+  builder.setInsertionPointToEnd(curBlock);
+  auto ifOp = builder.create<IfOp>(*currentOpLoc, conditionValue->front(),
+                                   *inputOps, successor);
+  auto *ifEntryBlock = ifOp.createIfBlock();
+  constexpr auto ifElseFilter =
+      ByteSequence<WasmBinaryEncoding::endByte,
+                   WasmBinaryEncoding::OpCode::elseOpCode>{};
+  auto parseIfRes = parseBlockContent(builder, ifEntryBlock, resTypes, *opLoc,
+                                      ifOp, ifElseFilter);
+  if (failed(parseIfRes))
+    return failure();
+  if (*parseIfRes == WasmBinaryEncoding::OpCode::elseOpCode) {
+    LDBG() << "  else block is present.";
+    Block *elseEntryBlock = ifOp.createElseBlock();
+    auto parseElseRes =
+        parseBlockContent(builder, elseEntryBlock, resTypes, *opLoc, ifOp);
+    if (failed(parseElseRes))
+      return failure();
+  }
+  builder.setInsertionPointToStart(successor);
+  return {ValueRange{successor->getArguments()}};
+}
+
+template <>
+inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
+    WasmBinaryEncoding::OpCode::branchIf>(OpBuilder &builder) {
+  auto level = parser.parseLiteral<uint32_t>();
+  if (failed(level))
+    return failure();
+  Block *curBlock = builder.getBlock();
+  Region *curRegion = curBlock->getParent();
+  auto sip = builder.saveInsertionPoint();
+  Block *elseBlock = builder.createBlock(curRegion, curRegion->end());
+  auto condition = popOperands(builder.getI32Type());
+  if (failed(condition))
+    return failure();
+  builder.restoreInsertionPoint(sip);
+  auto targetOp =
+      LabelBranchingOpInterface::getTargetOpFromBlock(curBlock, *level);
+  if (failed(targetOp))
+    return failure();
+  auto inputTypes = targetOp->getLabelTarget()->getArgumentTypes();
+  auto branchArgs = popOperands(inputTypes);
+  if (failed(branchArgs))
+    return failure();
+  builder.create<BranchIfOp>(*currentOpLoc, condition->front(),
+                             builder.getUI32IntegerAttr(*level), *branchArgs,
+                             elseBlock);
+  builder.setInsertionPointToStart(elseBlock);
+  return {*branchArgs};
+}
+
+template <>
+inline parsed_inst_t
+ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::call>(
+    OpBuilder &builder) {
+  auto loc = *currentOpLoc;
+  auto funcIdx = parser.parseLiteral<uint32_t>();
+  if (failed(funcIdx))
+    return failure();
+  if (*funcIdx >= symbols.funcSymbols.size())
+    return emitError(loc, "Invalid function index: ") << *funcIdx;
+  auto callee = symbols.funcSymbols[*funcIdx];
+  llvm::ArrayRef<Type> inTypes = callee.functionType.getInputs();
+  llvm::ArrayRef<Type> resTypes = callee.functionType.getResults();
+  parsed_inst_t inOperands = popOperands(inTypes);
+  if (failed(inOperands))
+    return failure();
+  auto callOp =
+      builder.create<FuncCallOp>(loc, resTypes, callee.symbol, *inOperands);
+  return {callOp.getResults()};
+}
+
 template <>
 inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
     WasmBinaryEncoding::OpCode::localGet>(OpBuilder &builder) {
@@ -1518,7 +1827,7 @@ WasmBinaryParser::parseSectionItem<WasmSectionType::EXPORT>(ParserHead &ph,
     return failure();
 
   Operation *op = SymbolTable::lookupSymbolIn(mOp, *currentSymbol);
-  SymbolTable::setSymbolVisibility(op, SymbolTable::Visibility::Public);
+  op->setAttr("sym_visibility", StringAttr::get(ctx, "public"));
   StringAttr symName = SymbolTable::getSymbolName(op);
   return SymbolTable{mOp}.rename(symName, *exportName);
 }
diff --git a/mlir/test/Target/Wasm/abs.mlir b/mlir/test/Target/Wasm/abs.mlir
index 9c45ba78507ad..eac4d79c7a991 100644
--- a/mlir/test/Target/Wasm/abs.mlir
+++ b/mlir/test/Target/Wasm/abs.mlir
@@ -12,12 +12,12 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @abs_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @abs_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.abs %[[VAL_0]] : f32
 // CHECK:           wasmssa.return %[[VAL_1]] : f32
 
-// CHECK-LABEL:   wasmssa.func @abs_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @abs_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.abs %[[VAL_0]] : f64
 // CHECK:           wasmssa.return %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/add_div.mlir b/mlir/test/Target/Wasm/add_div.mlir
new file mode 100644
index 0000000000000..7047639e1a574
--- /dev/null
+++ b/mlir/test/Target/Wasm/add_div.mlir
@@ -0,0 +1,40 @@
+// RUN: yaml2obj %S/inputs/add_div.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to create this test:
+ (module $test.wasm
+  (type (;0;) (func (param i32) (result i32)))
+  (type (;1;) (func (param i32 i32) (result i32)))
+  (import "env" "twoTimes" (func $twoTimes (type 0)))
+  (func $add (type 1) (param i32 i32) (result i32)
+    local.get 0
+    call $twoTimes
+    local.get 1
+    call $twoTimes
+    i32.add
+    i32.const 2
+    i32.div_s)
+  (memory (;0;) 2)
+  (global $__stack_pointer (mut i32) (i32.const 66560))
+  (export "memory" (memory 0))
+  (export "add" (func $add)))
+*/
+
+// CHECK-LABEL:   wasmssa.import_func "twoTimes" from "env" as @func_0 {sym_visibility = "nested", type = (i32) -> i32}
+
+// CHECK-LABEL:   wasmssa.func public @add(
+// CHECK-SAME:      %[[ARG0:.*]]: !wasmssa<local ref to i32>,
+// CHECK-SAME:      %[[ARG1:.*]]: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] :  ref to i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.call @func_0(%[[VAL_0]]) : (i32) -> i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.local_get %[[ARG1]] :  ref to i32
+// CHECK:           %[[VAL_3:.*]] = wasmssa.call @func_0(%[[VAL_2]]) : (i32) -> i32
+// CHECK:           %[[VAL_4:.*]] = wasmssa.add %[[VAL_1]] %[[VAL_3]] : i32
+// CHECK:           %[[VAL_5:.*]] = wasmssa.const 2 : i32
+// CHECK:           %[[VAL_6:.*]] = wasmssa.div_si %[[VAL_4]] %[[VAL_5]] : i32
+// CHECK:           wasmssa.return %[[VAL_6]] : i32
+// CHECK:         }
+// CHECK:         wasmssa.memory @memory public !wasmssa<limit[2:]>
+
+// CHECK-LABEL:   wasmssa.global @global_0 i32 mutable nested : {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 66560 : i32
+// CHECK:           wasmssa.return %[[VAL_0]] : i32
diff --git a/mlir/test/Target/Wasm/and.mlir b/mlir/test/Target/Wasm/and.mlir
index 4c0fea01b3ae6..5139e39a42d97 100644
--- a/mlir/test/Target/Wasm/and.mlir
+++ b/mlir/test/Target/Wasm/and.mlir
@@ -14,13 +14,13 @@
 )
 */
 
-// CHECK-LABEL: wasmssa.func @and_i32() -> i32 {
+// CHECK-LABEL: wasmssa.func public @and_i32() -> i32 {
 // CHECK:    %0 = wasmssa.const 10 : i32
 // CHECK:    %1 = wasmssa.const 3 : i32
 // CHECK:    %2 = wasmssa.and %0 %1 : i32
 // CHECK:    wasmssa.return %2 : i32
 
-// CHECK-LABEL: wasmssa.func @and_i64() -> i64 {
+// CHECK-LABEL: wasmssa.func public @and_i64() -> i64 {
 // CHECK:    %0 = wasmssa.const 10 : i64
 // CHECK:    %1 = wasmssa.const 3 : i64
 // CHECK:    %2 = wasmssa.and %0 %1 : i64
diff --git a/mlir/test/Target/Wasm/block.mlir b/mlir/test/Target/Wasm/block.mlir
new file mode 100644
index 0000000000000..8eac5475b8026
--- /dev/null
+++ b/mlir/test/Target/Wasm/block.mlir
@@ -0,0 +1,16 @@
+// RUN: yaml2obj %S/inputs/block.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to create this test:
+(module
+(func(export "i_am_a_block")
+(block $i_am_a_block)
+)
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func public @i_am_a_block() {
+// CHECK:           wasmssa.block : {
+// CHECK:             wasmssa.block_return
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1:
+// CHECK:           wasmssa.return
diff --git a/mlir/test/Target/Wasm/block_complete_type.mlir b/mlir/test/Target/Wasm/block_complete_type.mlir
new file mode 100644
index 0000000000000..348c8bbcba440
--- /dev/null
+++ b/mlir/test/Target/Wasm/block_complete_type.mlir
@@ -0,0 +1,24 @@
+// RUN: yaml2obj %S/inputs/block_complete_type.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to create this test:
+(module
+  (type (;0;) (func (param i32) (result i32)))
+  (type (;1;) (func (result i32)))
+  (func (;0;) (type 1) (result i32)
+    i32.const 14
+    block (param i32) (result i32)  ;; label = @1
+      i32.const 1
+      i32.add
+    end))
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 14 : i32
+// CHECK:           wasmssa.block(%[[VAL_0]]) : i32 : {
+// CHECK:           ^bb0(%[[VAL_1:.*]]: i32):
+// CHECK:             %[[VAL_2:.*]] = wasmssa.const 1 : i32
+// CHECK:             %[[VAL_3:.*]] = wasmssa.add %[[VAL_1]] %[[VAL_2]] : i32
+// CHECK:             wasmssa.block_return %[[VAL_3]] : i32
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1(%[[VAL_4:.*]]: i32):
+// CHECK:           wasmssa.return %[[VAL_4]] : i32
diff --git a/mlir/test/Target/Wasm/block_value_type.mlir b/mlir/test/Target/Wasm/block_value_type.mlir
new file mode 100644
index 0000000000000..4354b322cbd93
--- /dev/null
+++ b/mlir/test/Target/Wasm/block_value_type.mlir
@@ -0,0 +1,19 @@
+// RUN: yaml2obj %S/inputs/block_value_type.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to create this test:
+(module
+  (type (;0;) (func (result i32)))
+  (func (;0;) (type 0) (result i32)
+    block (result i32)  ;; label = @1
+      i32.const 17
+    end))
+*/
+
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> i32 {
+// CHECK:           wasmssa.block : {
+// CHECK:             %[[VAL_0:.*]] = wasmssa.const 17 : i32
+// CHECK:             wasmssa.block_return %[[VAL_0]] : i32
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1(%[[VAL_1:.*]]: i32):
+// CHECK:           wasmssa.return %[[VAL_1]] : i32
diff --git a/mlir/test/Target/Wasm/branch_if.mlir b/mlir/test/Target/Wasm/branch_if.mlir
new file mode 100644
index 0000000000000..a7561b8615d88
--- /dev/null
+++ b/mlir/test/Target/Wasm/branch_if.mlir
@@ -0,0 +1,29 @@
+// RUN: yaml2obj %S/inputs/branch_if.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to create this test:
+(module
+  (type $produce_i32 (func (result i32)))
+  (func (type $produce_i32)
+    (block $my_block (type $produce_i32)
+      i32.const 1
+      i32.const 2
+      br_if $my_block
+      i32.const 1
+      i32.add
+    )
+  )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> i32 {
+// CHECK:           wasmssa.block : {
+// CHECK:             %[[VAL_0:.*]] = wasmssa.const 1 : i32
+// CHECK:             %[[VAL_1:.*]] = wasmssa.const 2 : i32
+// CHECK:             wasmssa.branch_if %[[VAL_1]] to level 0 with args(%[[VAL_0]] : i32) else ^bb1
+// CHECK:           ^bb1:
+// CHECK:             %[[VAL_2:.*]] = wasmssa.const 1 : i32
+// CHECK:             %[[VAL_3:.*]] = wasmssa.add %[[VAL_0]] %[[VAL_2]] : i32
+// CHECK:             wasmssa.block_return %[[VAL_3]] : i32
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1(%[[VAL_4:.*]]: i32):
+// CHECK:           wasmssa.return %[[VAL_4]] : i32
diff --git a/mlir/test/Target/Wasm/call.mlir b/mlir/test/Target/Wasm/call.mlir
new file mode 100644
index 0000000000000..78406d9d8907e
--- /dev/null
+++ b/mlir/test/Target/Wasm/call.mlir
@@ -0,0 +1,17 @@
+// RUN: yaml2obj %S/inputs/call.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to create this test:
+(module
+(func $forty_two (result i32)
+i32.const 42)
+(func(export "forty_two")(result i32)
+call $forty_two))
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.const 42 : i32
+// CHECK:           wasmssa.return %[[VAL_0]] : i32
+
+// CHECK-LABEL:   wasmssa.func public @forty_two() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.call @func_0 : () -> i32
+// CHECK:           wasmssa.return %[[VAL_0]] : i32
diff --git a/mlir/test/Target/Wasm/clz.mlir b/mlir/test/Target/Wasm/clz.mlir
index 3e6641d9a2a96..c7246f6acbf6c 100644
--- a/mlir/test/Target/Wasm/clz.mlir
+++ b/mlir/test/Target/Wasm/clz.mlir
@@ -14,12 +14,12 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @clz_i32() -> i32 {
+// CHECK-LABEL:   wasmssa.func public @clz_i32() -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.clz %[[VAL_0]] : i32
 // CHECK:           wasmssa.return %[[VAL_1]] : i32
 
-// CHECK-LABEL:   wasmssa.func @clz_i64() -> i64 {
+// CHECK-LABEL:   wasmssa.func public @clz_i64() -> i64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.clz %[[VAL_0]] : i64
 // CHECK:           wasmssa.return %[[VAL_1]] : i64
diff --git a/mlir/test/Target/Wasm/convert.mlir b/mlir/test/Target/Wasm/convert.mlir
index 8ecb0d117942e..cfd4b9a6fc61b 100644
--- a/mlir/test/Target/Wasm/convert.mlir
+++ b/mlir/test/Target/Wasm/convert.mlir
@@ -44,42 +44,42 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @convert_i32_u_to_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @convert_i32_u_to_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.convert_u %[[VAL_0]] : i32 to f32
 // CHECK:           wasmssa.return %[[VAL_1]] : f32
 
-// CHECK-LABEL:   wasmssa.func @convert_i32_s_to_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @convert_i32_s_to_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 42 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.convert_s %[[VAL_0]] : i32 to f32
 // CHECK:           wasmssa.return %[[VAL_1]] : f32
 
-// CHECK-LABEL:   wasmssa.func @convert_i64_u_to_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @convert_i64_u_to_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 17 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.convert_u %[[VAL_0]] : i64 to f32
 // CHECK:           wasmssa.return %[[VAL_1]] : f32
 
-// CHECK-LABEL:   wasmssa.func @convert_i64s_to_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @convert_i64s_to_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.convert_s %[[VAL_0]] : i64 to f32
 // CHECK:           wasmssa.return %[[VAL_1]] : f32
 
-// CHECK-LABEL:   wasmssa.func @convert_i32_u_to_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @convert_i32_u_to_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.convert_u %[[VAL_0]] : i32 to f64
 // CHECK:           wasmssa.return %[[VAL_1]] : f64
 
-// CHECK-LABEL:   wasmssa.func @convert_i32_s_to_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @convert_i32_s_to_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 42 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.convert_s %[[VAL_0]] : i32 to f64
 // CHECK:           wasmssa.return %[[VAL_1]] : f64
 
-// CHECK-LABEL:   wasmssa.func @convert_i64_u_to_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @convert_i64_u_to_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 17 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.convert_u %[[VAL_0]] : i64 to f64
 // CHECK:           wasmssa.return %[[VAL_1]] : f64
 
-// CHECK-LABEL:   wasmssa.func @convert_i64s_to_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @convert_i64s_to_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.convert_s %[[VAL_0]] : i64 to f64
 // CHECK:           wasmssa.return %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/copysign.mlir b/mlir/test/Target/Wasm/copysign.mlir
index 33d7a56694c1c..88414cc34dcbd 100644
--- a/mlir/test/Target/Wasm/copysign.mlir
+++ b/mlir/test/Target/Wasm/copysign.mlir
@@ -16,14 +16,14 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @copysign_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @copysign_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.000000e+00 : f32
 // CHECK:           %[[VAL_2:.*]] = wasmssa.copysign %[[VAL_0]] %[[VAL_1]] : f32
 // CHECK:           wasmssa.return %[[VAL_2]] : f32
 // CHECK:         }
 
-// CHECK-LABEL:   wasmssa.func @copysign_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @copysign_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.000000e+00 : f64
 // CHECK:           %[[VAL_2:.*]] = wasmssa.copysign %[[VAL_0]] %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/ctz.mlir b/mlir/test/Target/Wasm/ctz.mlir
index 6c0806f62303c..00caf6bfd076b 100644
--- a/mlir/test/Target/Wasm/ctz.mlir
+++ b/mlir/test/Target/Wasm/ctz.mlir
@@ -14,12 +14,12 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @ctz_i32() -> i32 {
+// CHECK-LABEL:   wasmssa.func public @ctz_i32() -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.ctz %[[VAL_0]] : i32
 // CHECK:           wasmssa.return %[[VAL_1]] : i32
 
-// CHECK-LABEL:   wasmssa.func @ctz_i64() -> i64 {
+// CHECK-LABEL:   wasmssa.func public @ctz_i64() -> i64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.ctz %[[VAL_0]] : i64
 // CHECK:           wasmssa.return %[[VAL_1]] : i64
diff --git a/mlir/test/Target/Wasm/div.mlir b/mlir/test/Target/Wasm/div.mlir
index c91f7809a255d..38797594b2f53 100644
--- a/mlir/test/Target/Wasm/div.mlir
+++ b/mlir/test/Target/Wasm/div.mlir
@@ -66,61 +66,61 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @div_u_i32() -> i32 {
+// CHECK-LABEL:   wasmssa.func public @div_u_i32() -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 2 : i32
 // CHECK:           %[[VAL_2:.*]] = wasmssa.div_ui %[[VAL_0]] %[[VAL_1]] : i32
 // CHECK:           wasmssa.return %[[VAL_2]] : i32
 
-// CHECK-LABEL:   wasmssa.func @div_u_i32_zero() -> i32 {
+// CHECK-LABEL:   wasmssa.func public @div_u_i32_zero() -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 0 : i32
 // CHECK:           %[[VAL_2:.*]] = wasmssa.div_ui %[[VAL_0]] %[[VAL_1]] : i32
 // CHECK:           wasmssa.return %[[VAL_2]] : i32
 
-// CHECK-LABEL:   wasmssa.func @div_s_i32() -> i32 {
+// CHECK-LABEL:   wasmssa.func public @div_s_i32() -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 2 : i32
 // CHECK:           %[[VAL_2:.*]] = wasmssa.div_si %[[VAL_0]] %[[VAL_1]] : i32
 // CHECK:           wasmssa.return %[[VAL_2]] : i32
 
-// CHECK-LABEL:   wasmssa.func @div_s_i32_zero() -> i32 {
+// CHECK-LABEL:   wasmssa.func public @div_s_i32_zero() -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 0 : i32
 // CHECK:           %[[VAL_2:.*]] = wasmssa.div_si %[[VAL_0]] %[[VAL_1]] : i32
 // CHECK:           wasmssa.return %[[VAL_2]] : i32
 
-// CHECK-LABEL:   wasmssa.func @div_u_i64() -> i64 {
+// CHECK-LABEL:   wasmssa.func public @div_u_i64() -> i64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 2 : i64
 // CHECK:           %[[VAL_2:.*]] = wasmssa.div_ui %[[VAL_0]] %[[VAL_1]] : i64
 // CHECK:           wasmssa.return %[[VAL_2]] : i64
 
-// CHECK-LABEL:   wasmssa.func @div_u_i64_zero() -> i64 {
+// CHECK-LABEL:   wasmssa.func public @div_u_i64_zero() -> i64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 0 : i64
 // CHECK:           %[[VAL_2:.*]] = wasmssa.div_ui %[[VAL_0]] %[[VAL_1]] : i64
 // CHECK:           wasmssa.return %[[VAL_2]] : i64
 
-// CHECK-LABEL:   wasmssa.func @div_s_i64() -> i64 {
+// CHECK-LABEL:   wasmssa.func public @div_s_i64() -> i64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 2 : i64
 // CHECK:           %[[VAL_2:.*]] = wasmssa.div_si %[[VAL_0]] %[[VAL_1]] : i64
 // CHECK:           wasmssa.return %[[VAL_2]] : i64
 
-// CHECK-LABEL:   wasmssa.func @div_s_i64_zero() -> i64 {
+// CHECK-LABEL:   wasmssa.func public @div_s_i64_zero() -> i64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 0 : i64
 // CHECK:           %[[VAL_2:.*]] = wasmssa.div_si %[[VAL_0]] %[[VAL_1]] : i64
 // CHECK:           wasmssa.return %[[VAL_2]] : i64
 
-// CHECK-LABEL:   wasmssa.func @div_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @div_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 2.000000e+00 : f32
 // CHECK:           %[[VAL_2:.*]] = wasmssa.div %[[VAL_0]] %[[VAL_1]] : f32
 // CHECK:           wasmssa.return %[[VAL_2]] : f32
 
-// CHECK-LABEL:   wasmssa.func @div_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @div_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 2.000000e+00 : f64
 // CHECK:           %[[VAL_2:.*]] = wasmssa.div %[[VAL_0]] %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/double_nested_loop.mlir b/mlir/test/Target/Wasm/double_nested_loop.mlir
new file mode 100644
index 0000000000000..26d40c356b65b
--- /dev/null
+++ b/mlir/test/Target/Wasm/double_nested_loop.mlir
@@ -0,0 +1,63 @@
+// RUN: yaml2obj %S/inputs/double_nested_loop.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/*
+(module
+  (func
+    ;; create a local variable and initialize it to 0
+    (local $i i32)
+    (local $j i32)
+
+    (loop $my_loop
+
+      ;; add one to $i
+      local.get $i
+      i32.const 1
+      i32.add
+      local.set $i
+      (loop $my_second_loop (result i32)
+        i32.const 1
+        local.get $j
+        i32.const 12
+        i32.add
+        local.tee $j
+        local.get $i
+        i32.gt_s
+        br_if $my_second_loop
+      )
+      i32.const 10
+      i32.lt_s
+      br_if $my_loop
+    )
+  )
+)
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.local of type i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.local of type i32
+// CHECK:           wasmssa.loop : {
+// CHECK:             %[[VAL_2:.*]] = wasmssa.local_get %[[VAL_0]] :  ref to i32
+// CHECK:             %[[VAL_3:.*]] = wasmssa.const 1 : i32
+// CHECK:             %[[VAL_4:.*]] = wasmssa.add %[[VAL_2]] %[[VAL_3]] : i32
+// CHECK:             wasmssa.local_set %[[VAL_0]] :  ref to i32 to %[[VAL_4]] : i32
+// CHECK:             wasmssa.loop : {
+// CHECK:               %[[VAL_5:.*]] = wasmssa.const 1 : i32
+// CHECK:               %[[VAL_6:.*]] = wasmssa.local_get %[[VAL_1]] :  ref to i32
+// CHECK:               %[[VAL_7:.*]] = wasmssa.const 12 : i32
+// CHECK:               %[[VAL_8:.*]] = wasmssa.add %[[VAL_6]] %[[VAL_7]] : i32
+// CHECK:               %[[VAL_9:.*]] = wasmssa.local_tee %[[VAL_1]] :  ref to i32 to %[[VAL_8]] : i32
+// CHECK:               %[[VAL_10:.*]] = wasmssa.local_get %[[VAL_0]] :  ref to i32
+// CHECK:               %[[VAL_11:.*]] = wasmssa.gt_si %[[VAL_9]] %[[VAL_10]] : i32 -> i32
+// CHECK:               wasmssa.branch_if %[[VAL_11]] to level 0 else ^bb1
+// CHECK:             ^bb1:
+// CHECK:               wasmssa.block_return %[[VAL_5]] : i32
+// CHECK:             }> ^bb1
+// CHECK:           ^bb1(%[[VAL_12:.*]]: i32):
+// CHECK:             %[[VAL_13:.*]] = wasmssa.const 10 : i32
+// CHECK:             %[[VAL_14:.*]] = wasmssa.lt_si %[[VAL_12]] %[[VAL_13]] : i32 -> i32
+// CHECK:             wasmssa.branch_if %[[VAL_14]] to level 0 else ^bb2
+// CHECK:           ^bb2:
+// CHECK:             wasmssa.block_return
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1:
+// CHECK:           wasmssa.return
diff --git a/mlir/test/Target/Wasm/empty_blocks_list_and_stack.mlir b/mlir/test/Target/Wasm/empty_blocks_list_and_stack.mlir
new file mode 100644
index 0000000000000..fa26db362c3d3
--- /dev/null
+++ b/mlir/test/Target/Wasm/empty_blocks_list_and_stack.mlir
@@ -0,0 +1,53 @@
+// RUN: yaml2obj %S/inputs/empty_blocks_list_and_stack.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to create this test:
+(module
+  (func (param $num i32)
+    (block $b1
+        (block $b2
+            (block $b3
+            )
+        )
+    )
+  )
+
+  (func (param $num i32)
+    (block $b1)
+    (block $b2)
+    (block $b3)
+  )
+)
+
+*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0(
+// CHECK-SAME:      %[[ARG0:.*]]: !wasmssa<local ref to i32>) {
+// CHECK:           wasmssa.block : {
+// CHECK:             wasmssa.block : {
+// CHECK:               wasmssa.block : {
+// CHECK:                 wasmssa.block_return
+// CHECK:               }> ^bb1
+// CHECK:             ^bb1:
+// CHECK:               wasmssa.block_return
+// CHECK:             }> ^bb1
+// CHECK:           ^bb1:
+// CHECK:             wasmssa.block_return
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1:
+// CHECK:           wasmssa.return
+
+// CHECK-LABEL:   wasmssa.func nested @func_1(
+// CHECK-SAME:      %[[ARG0:.*]]: !wasmssa<local ref to i32>) {
+// CHECK:           wasmssa.block : {
+// CHECK:             wasmssa.block_return
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1:
+// CHECK:           wasmssa.block : {
+// CHECK:             wasmssa.block_return
+// CHECK:           }> ^bb2
+// CHECK:         ^bb2:
+// CHECK:           wasmssa.block : {
+// CHECK:             wasmssa.block_return
+// CHECK:           }> ^bb3
+// CHECK:         ^bb3:
+// CHECK:           wasmssa.return
diff --git a/mlir/test/Target/Wasm/eqz.mlir b/mlir/test/Target/Wasm/eqz.mlir
index e4972db1e3a9e..e2849743305e9 100644
--- a/mlir/test/Target/Wasm/eqz.mlir
+++ b/mlir/test/Target/Wasm/eqz.mlir
@@ -10,12 +10,12 @@
     i64.eqz)
 )
 */
-// CHECK-LABEL:   wasmssa.func @eqz_i32() -> i32 {
+// CHECK-LABEL:   wasmssa.func public @eqz_i32() -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 13 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.eqz %[[VAL_0]] : i32 -> i32
 // CHECK:           wasmssa.return %[[VAL_1]] : i32
 
-// CHECK-LABEL:   wasmssa.func @eqz_i64() -> i32 {
+// CHECK-LABEL:   wasmssa.func public @eqz_i64() -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 13 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.eqz %[[VAL_0]] : i64 -> i32
 // CHECK:           wasmssa.return %[[VAL_1]] : i32
diff --git a/mlir/test/Target/Wasm/if.mlir b/mlir/test/Target/Wasm/if.mlir
new file mode 100644
index 0000000000000..7b9e6318f88f4
--- /dev/null
+++ b/mlir/test/Target/Wasm/if.mlir
@@ -0,0 +1,112 @@
+// RUN: yaml2obj %S/inputs/if.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Source code used to create this test:
+(module
+(type $intMapper (func (param $input i32) (result i32)))
+(func $if_else (type $intMapper)
+  local.get 0
+  i32.const 1
+  i32.and
+  if $isOdd (result i32)
+    local.get 0
+    i32.const 3
+    i32.mul
+    i32.const 1
+    i32.add
+  else
+    local.get 0
+    i32.const 1
+    i32.shr_u
+  end
+)
+
+(func $if_only (type $intMapper)
+  local.get 0
+  local.get 0
+  i32.const 1
+  i32.and
+  if $isOdd (type $intMapper)
+    i32.const 1
+    i32.add
+  end
+)
+
+(func $if_if (type $intMapper)
+  local.get 0
+  i32.ctz
+  if $isEven (result i32)
+    i32.const 2
+    local.get 0
+    i32.const 1
+    i32.shr_u
+    i32.ctz
+    if $isMultipleOfFour (type $intMapper)
+      i32.const 2
+      i32.add
+    end
+  else
+    i32.const 1
+  end
+)
+)
+*/
+// CHECK-LABEL:   wasmssa.func nested @func_0(
+// CHECK-SAME:      %[[ARG0:.*]]: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] :  ref to i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.const 1 : i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.and %[[VAL_0]] %[[VAL_1]] : i32
+// CHECK:           wasmssa.if %[[VAL_2]] : {
+// CHECK:             %[[VAL_3:.*]] = wasmssa.local_get %[[ARG0]] :  ref to i32
+// CHECK:             %[[VAL_4:.*]] = wasmssa.const 3 : i32
+// CHECK:             %[[VAL_5:.*]] = wasmssa.mul %[[VAL_3]] %[[VAL_4]] : i32
+// 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:             %[[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
+// CHECK:             wasmssa.block_return %[[VAL_10]] : i32
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1(%[[VAL_11:.*]]: i32):
+// CHECK:           wasmssa.return %[[VAL_11]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_1(
+// CHECK-SAME:      %[[ARG0:.*]]: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] :  ref to i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.local_get %[[ARG0]] :  ref to i32
+// CHECK:           %[[VAL_2:.*]] = wasmssa.const 1 : i32
+// CHECK:           %[[VAL_3:.*]] = wasmssa.and %[[VAL_1]] %[[VAL_2]] : i32
+// CHECK:           wasmssa.if %[[VAL_3]](%[[VAL_0]]) : i32 : {
+// CHECK:           ^bb0(%[[VAL_4:.*]]: i32):
+// CHECK:             %[[VAL_5:.*]] = wasmssa.const 1 : i32
+// CHECK:             %[[VAL_6:.*]] = wasmssa.add %[[VAL_4]] %[[VAL_5]] : i32
+// CHECK:             wasmssa.block_return %[[VAL_6]] : i32
+// CHECK:           } > ^bb1
+// CHECK:         ^bb1(%[[VAL_7:.*]]: i32):
+// CHECK:           wasmssa.return %[[VAL_7]] : i32
+
+// CHECK-LABEL:   wasmssa.func nested @func_2(
+// CHECK-SAME:      %[[ARG0:.*]]: !wasmssa<local ref to i32>) -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] :  ref to i32
+// CHECK:           %[[VAL_1:.*]] = wasmssa.ctz %[[VAL_0]] : i32
+// CHECK:           wasmssa.if %[[VAL_1]] : {
+// CHECK:             %[[VAL_2:.*]] = wasmssa.const 2 : i32
+// CHECK:             %[[VAL_3:.*]] = wasmssa.local_get %[[ARG0]] :  ref to i32
+// CHECK:             %[[VAL_4:.*]] = wasmssa.const 1 : i32
+// CHECK:             %[[VAL_5:.*]] = wasmssa.shr_u %[[VAL_3]] by %[[VAL_4]] bits : i32
+// CHECK:             %[[VAL_6:.*]] = wasmssa.ctz %[[VAL_5]] : i32
+// CHECK:             wasmssa.if %[[VAL_6]](%[[VAL_2]]) : i32 : {
+// CHECK:             ^bb0(%[[VAL_7:.*]]: i32):
+// CHECK:               %[[VAL_8:.*]] = wasmssa.const 2 : i32
+// CHECK:               %[[VAL_9:.*]] = wasmssa.add %[[VAL_7]] %[[VAL_8]] : i32
+// CHECK:               wasmssa.block_return %[[VAL_9]] : i32
+// CHECK:             } > ^bb1
+// CHECK:           ^bb1(%[[VAL_10:.*]]: i32):
+// CHECK:             wasmssa.block_return %[[VAL_10]] : i32
+// CHECK:           } "else "{
+// CHECK:             %[[VAL_11:.*]] = wasmssa.const 1 : i32
+// CHECK:             wasmssa.block_return %[[VAL_11]] : i32
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1(%[[VAL_12:.*]]: i32):
+// CHECK:           wasmssa.return %[[VAL_12]] : i32
diff --git a/mlir/test/Target/Wasm/inputs/add_div.yaml.wasm b/mlir/test/Target/Wasm/inputs/add_div.yaml.wasm
new file mode 100644
index 0000000000000..865c31581a82f
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/add_div.yaml.wasm
@@ -0,0 +1,50 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:
+          - I32
+        ReturnTypes:
+          - I32
+      - Index:           1
+        ParamTypes:
+          - I32
+          - I32
+        ReturnTypes:
+          - I32
+  - Type:            IMPORT
+    Imports:
+      - Module:          env
+        Field:           twoTimes
+        Kind:            FUNCTION
+        SigIndex:        0
+  - Type:            FUNCTION
+    FunctionTypes:   [ 1 ]
+  - Type:            MEMORY
+    Memories:
+      - Minimum:         0x2
+  - Type:            GLOBAL
+    Globals:
+      - Index:           0
+        Type:            I32
+        Mutable:         true
+        InitExpr:
+          Opcode:          I32_CONST
+          Value:           66560
+  - Type:            EXPORT
+    Exports:
+      - Name:            memory
+        Kind:            MEMORY
+        Index:           0
+      - Name:            add
+        Kind:            FUNCTION
+        Index:           1
+  - Type:            CODE
+    Functions:
+      - Index:           1
+        Locals:          []
+        Body:            20001000200110006A41026D0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/block.yaml.wasm b/mlir/test/Target/Wasm/inputs/block.yaml.wasm
new file mode 100644
index 0000000000000..dd5118a119fa2
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/block.yaml.wasm
@@ -0,0 +1,22 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:     []
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0 ]
+  - Type:            EXPORT
+    Exports:
+      - Name:            i_am_a_block
+        Kind:            FUNCTION
+        Index:           0
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            02400B0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/block_complete_type.yaml.wasm b/mlir/test/Target/Wasm/inputs/block_complete_type.yaml.wasm
new file mode 100644
index 0000000000000..7a125bfa06d59
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/block_complete_type.yaml.wasm
@@ -0,0 +1,23 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:
+          - I32
+        ReturnTypes:
+          - I32
+      - Index:           1
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 1 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            410E020041016A0B0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/block_value_type.yaml.wasm b/mlir/test/Target/Wasm/inputs/block_value_type.yaml.wasm
new file mode 100644
index 0000000000000..4ba291d6ac7a5
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/block_value_type.yaml.wasm
@@ -0,0 +1,18 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            027F41110B0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/branch_if.yaml.wasm b/mlir/test/Target/Wasm/inputs/branch_if.yaml.wasm
new file mode 100644
index 0000000000000..40536ed3a8723
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/branch_if.yaml.wasm
@@ -0,0 +1,18 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            027F410141020D0041016A0B0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/call.yaml.wasm b/mlir/test/Target/Wasm/inputs/call.yaml.wasm
new file mode 100644
index 0000000000000..535a623edc6da
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/call.yaml.wasm
@@ -0,0 +1,26 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0 ]
+  - Type:            EXPORT
+    Exports:
+      - Name:            forty_two
+        Kind:            FUNCTION
+        Index:           1
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            412A0B
+      - Index:           1
+        Locals:          []
+        Body:            10000B
+...
diff --git a/mlir/test/Target/Wasm/inputs/double_nested_loop.yaml.wasm b/mlir/test/Target/Wasm/inputs/double_nested_loop.yaml.wasm
new file mode 100644
index 0000000000000..41a2944249eba
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/double_nested_loop.yaml.wasm
@@ -0,0 +1,19 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:     []
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:
+          - Type:            I32
+            Count:           2
+        Body:            0340200041016A2100037F41012001410C6A220120004A0D000B410A480D000B0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/empty_blocks_list_and_stack.yaml.wasm b/mlir/test/Target/Wasm/inputs/empty_blocks_list_and_stack.yaml.wasm
new file mode 100644
index 0000000000000..3171409dff954
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/empty_blocks_list_and_stack.yaml.wasm
@@ -0,0 +1,21 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:
+          - I32
+        ReturnTypes:     []
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            0240024002400B0B0B0B
+      - Index:           1
+        Locals:          []
+        Body:            02400B02400B02400B0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/if.yaml.wasm b/mlir/test/Target/Wasm/inputs/if.yaml.wasm
new file mode 100644
index 0000000000000..ccc38f676e2e4
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/if.yaml.wasm
@@ -0,0 +1,25 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:
+          - I32
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0, 0, 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            2000410171047F200041036C41016A0520004101760B0B
+      - Index:           1
+        Locals:          []
+        Body:            20002000410171040041016A0B0B
+      - Index:           2
+        Locals:          []
+        Body:            200068047F4102200041017668040041026A0B0541010B0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/loop.yaml.wasm b/mlir/test/Target/Wasm/inputs/loop.yaml.wasm
new file mode 100644
index 0000000000000..9d33894bfea50
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/loop.yaml.wasm
@@ -0,0 +1,17 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:     []
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:          []
+        Body:            03400B0B
+...
diff --git a/mlir/test/Target/Wasm/inputs/loop_with_inst.yaml.wasm b/mlir/test/Target/Wasm/inputs/loop_with_inst.yaml.wasm
new file mode 100644
index 0000000000000..4b8cc545fe0e0
--- /dev/null
+++ b/mlir/test/Target/Wasm/inputs/loop_with_inst.yaml.wasm
@@ -0,0 +1,20 @@
+--- !WASM
+FileHeader:
+  Version:         0x1
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - Index:           0
+        ParamTypes:      []
+        ReturnTypes:
+          - I32
+  - Type:            FUNCTION
+    FunctionTypes:   [ 0 ]
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:
+          - Type:            I32
+            Count:           1
+        Body:            037F200041016A21002000410A480B0B
+...
diff --git a/mlir/test/Target/Wasm/loop.mlir b/mlir/test/Target/Wasm/loop.mlir
new file mode 100644
index 0000000000000..8eb348f1b8adb
--- /dev/null
+++ b/mlir/test/Target/Wasm/loop.mlir
@@ -0,0 +1,17 @@
+// RUN: yaml2obj %S/inputs/loop.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* IR generated from:
+(module
+  (func
+    (loop $my_loop
+    )
+  )
+)*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() {
+// CHECK:           wasmssa.loop : {
+// CHECK:             wasmssa.block_return
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1:
+// CHECK:           wasmssa.return
+// CHECK:         }
diff --git a/mlir/test/Target/Wasm/loop_with_inst.mlir b/mlir/test/Target/Wasm/loop_with_inst.mlir
new file mode 100644
index 0000000000000..84beb2565ef63
--- /dev/null
+++ b/mlir/test/Target/Wasm/loop_with_inst.mlir
@@ -0,0 +1,33 @@
+// RUN: yaml2obj %S/inputs/loop_with_inst.yaml.wasm -o - | mlir-translate --import-wasm | FileCheck %s
+
+/* Code used to create this test:
+
+(module
+  (func (result i32)
+    (local $i i32)
+    (loop $my_loop (result i32)
+      local.get $i
+      i32.const 1
+      i32.add
+      local.set $i
+      local.get $i
+      i32.const 10
+      i32.lt_s
+    )
+  )
+)*/
+
+// CHECK-LABEL:   wasmssa.func nested @func_0() -> i32 {
+// CHECK:           %[[VAL_0:.*]] = wasmssa.local of type i32
+// CHECK:           wasmssa.loop : {
+// CHECK:             %[[VAL_1:.*]] = wasmssa.local_get %[[VAL_0]] :  ref to i32
+// CHECK:             %[[VAL_2:.*]] = wasmssa.const 1 : i32
+// CHECK:             %[[VAL_3:.*]] = wasmssa.add %[[VAL_1]] %[[VAL_2]] : i32
+// CHECK:             wasmssa.local_set %[[VAL_0]] :  ref to i32 to %[[VAL_3]] : i32
+// CHECK:             %[[VAL_4:.*]] = wasmssa.local_get %[[VAL_0]] :  ref to i32
+// CHECK:             %[[VAL_5:.*]] = wasmssa.const 10 : i32
+// CHECK:             %[[VAL_6:.*]] = wasmssa.lt_si %[[VAL_4]] %[[VAL_5]] : i32 -> i32
+// CHECK:             wasmssa.block_return %[[VAL_6]] : i32
+// CHECK:           }> ^bb1
+// CHECK:         ^bb1(%[[VAL_7:.*]]: i32):
+// CHECK:           wasmssa.return %[[VAL_7]] : i32
diff --git a/mlir/test/Target/Wasm/max.mlir b/mlir/test/Target/Wasm/max.mlir
index 4ef2042d923b6..d2aaca1267600 100644
--- a/mlir/test/Target/Wasm/max.mlir
+++ b/mlir/test/Target/Wasm/max.mlir
@@ -16,14 +16,14 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @min_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @min_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.000000e+00 : f32
 // CHECK:           %[[VAL_2:.*]] = wasmssa.max %[[VAL_0]] %[[VAL_1]] : f32
 // CHECK:           wasmssa.return %[[VAL_2]] : f32
 
 
-// CHECK-LABEL:   wasmssa.func @min_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @min_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.000000e+00 : f64
 // CHECK:           %[[VAL_2:.*]] = wasmssa.max %[[VAL_0]] %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/min.mlir b/mlir/test/Target/Wasm/min.mlir
index 1058c7d32be71..c27602af25163 100644
--- a/mlir/test/Target/Wasm/min.mlir
+++ b/mlir/test/Target/Wasm/min.mlir
@@ -16,13 +16,13 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @min_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @min_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.000000e+00 : f32
 // CHECK:           %[[VAL_2:.*]] = wasmssa.min %[[VAL_0]] %[[VAL_1]] : f32
 // CHECK:           wasmssa.return %[[VAL_2]] : f32
 
-// CHECK-LABEL:   wasmssa.func @min_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @min_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.const 1.000000e+00 : f64
 // CHECK:           %[[VAL_2:.*]] = wasmssa.min %[[VAL_0]] %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/neg.mlir b/mlir/test/Target/Wasm/neg.mlir
index 5811ab50348bd..88633d8244b94 100644
--- a/mlir/test/Target/Wasm/neg.mlir
+++ b/mlir/test/Target/Wasm/neg.mlir
@@ -12,12 +12,12 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @neg_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @neg_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.neg %[[VAL_0]] : f32
 // CHECK:           wasmssa.return %[[VAL_1]] : f32
 
-// CHECK-LABEL:   wasmssa.func @neg_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @neg_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.neg %[[VAL_0]] : f64
 // CHECK:           wasmssa.return %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/or.mlir b/mlir/test/Target/Wasm/or.mlir
index 521f2bac9fa6a..ea2e6c63b5f41 100644
--- a/mlir/test/Target/Wasm/or.mlir
+++ b/mlir/test/Target/Wasm/or.mlir
@@ -14,13 +14,13 @@
 )
 */
 
-// CHECK-LABEL: wasmssa.func @or_i32() -> i32 {
+// CHECK-LABEL: wasmssa.func public @or_i32() -> i32 {
 // CHECK:    %0 = wasmssa.const 10 : i32
 // CHECK:    %1 = wasmssa.const 3 : i32
 // CHECK:    %2 = wasmssa.or %0 %1 : i32
 // CHECK:    wasmssa.return %2 : i32
 
-// CHECK-LABEL: wasmssa.func @or_i64() -> i64 {
+// CHECK-LABEL: wasmssa.func public @or_i64() -> i64 {
 // CHECK:    %0 = wasmssa.const 10 : i64
 // CHECK:    %1 = wasmssa.const 3 : i64
 // CHECK:    %2 = wasmssa.or %0 %1 : i64
diff --git a/mlir/test/Target/Wasm/popcnt.mlir b/mlir/test/Target/Wasm/popcnt.mlir
index 235333a085177..fc87bc7f37f8b 100644
--- a/mlir/test/Target/Wasm/popcnt.mlir
+++ b/mlir/test/Target/Wasm/popcnt.mlir
@@ -14,12 +14,12 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @popcnt_i32() -> i32 {
+// CHECK-LABEL:   wasmssa.func public @popcnt_i32() -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.popcnt %[[VAL_0]] : i32
 // CHECK:           wasmssa.return %[[VAL_1]] : i32
 
-// CHECK-LABEL:   wasmssa.func @popcnt_i64() -> i64 {
+// CHECK-LABEL:   wasmssa.func public @popcnt_i64() -> i64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 10 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.popcnt %[[VAL_0]] : i64
 // CHECK:           wasmssa.return %[[VAL_1]] : i64
diff --git a/mlir/test/Target/Wasm/reinterpret.mlir b/mlir/test/Target/Wasm/reinterpret.mlir
index 7528ebc700401..e3abb1c4a93d2 100644
--- a/mlir/test/Target/Wasm/reinterpret.mlir
+++ b/mlir/test/Target/Wasm/reinterpret.mlir
@@ -25,22 +25,22 @@ Test generated from:
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @i32.reinterpret_f32() -> i32 {
+// CHECK-LABEL:   wasmssa.func public @i32.reinterpret_f32() -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const -1.000000e+00 : f32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.reinterpret %[[VAL_0]] : f32 as i32
 // CHECK:           wasmssa.return %[[VAL_1]] : i32
 
-// CHECK-LABEL:   wasmssa.func @i64.reinterpret_f64() -> i64 {
+// CHECK-LABEL:   wasmssa.func public @i64.reinterpret_f64() -> i64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const -1.000000e+00 : f64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.reinterpret %[[VAL_0]] : f64 as i64
 // CHECK:           wasmssa.return %[[VAL_1]] : i64
 
-// CHECK-LABEL:   wasmssa.func @f32.reinterpret_i32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @f32.reinterpret_i32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const -1 : i32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.reinterpret %[[VAL_0]] : i32 as f32
 // CHECK:           wasmssa.return %[[VAL_1]] : f32
 
-// CHECK-LABEL:   wasmssa.func @f64.reinterpret_i64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @f64.reinterpret_i64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const -1 : i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.reinterpret %[[VAL_0]] : i64 as f64
 // CHECK:           wasmssa.return %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/rem.mlir b/mlir/test/Target/Wasm/rem.mlir
index b19b8d9d45ed7..49e2eecdbe963 100644
--- a/mlir/test/Target/Wasm/rem.mlir
+++ b/mlir/test/Target/Wasm/rem.mlir
@@ -24,28 +24,28 @@
 )
 */
 
-// CHECK-LABEL: wasmssa.func @rem_u_i32() -> i32 {
+// CHECK-LABEL: wasmssa.func public @rem_u_i32() -> i32 {
 // CHECK:    %0 = wasmssa.const 10 : i32
 // CHECK:    %1 = wasmssa.const 3 : i32
 // CHECK:    %2 = wasmssa.rem_ui %0 %1 : i32
 // CHECK:    wasmssa.return %2 : i32
 // CHECK:  }
 
-// CHECK-LABEL: wasmssa.func @rem_u_i64() -> i64 {
+// CHECK-LABEL: wasmssa.func public @rem_u_i64() -> i64 {
 // CHECK:    %0 = wasmssa.const 10 : i64
 // CHECK:    %1 = wasmssa.const 3 : i64
 // CHECK:    %2 = wasmssa.rem_ui %0 %1 : i64
 // CHECK:    wasmssa.return %2 : i64
 // CHECK:  }
 
-// CHECK-LABEL:  wasmssa.func @rem_s_i32() -> i32 {
+// CHECK-LABEL:  wasmssa.func public @rem_s_i32() -> i32 {
 // CHECK:    %0 = wasmssa.const 10 : i32
 // CHECK:    %1 = wasmssa.const 3 : i32
 // CHECK:    %2 = wasmssa.rem_si %0 %1 : i32
 // CHECK:    wasmssa.return %2 : i32
 // CHECK:  }
 
-// CHECK-LABEL:  wasmssa.func @rem_s_i64() -> i64 {
+// CHECK-LABEL:  wasmssa.func public @rem_s_i64() -> i64 {
 // CHECK:    %0 = wasmssa.const 10 : i64
 // CHECK:    %1 = wasmssa.const 3 : i64
 // CHECK:    %2 = wasmssa.rem_si %0 %1 : i64
diff --git a/mlir/test/Target/Wasm/rotl.mlir b/mlir/test/Target/Wasm/rotl.mlir
index ec573554f0a8c..faa0eeb540dd1 100644
--- a/mlir/test/Target/Wasm/rotl.mlir
+++ b/mlir/test/Target/Wasm/rotl.mlir
@@ -14,13 +14,13 @@
 )
 */
 
-// CHECK-LABEL: wasmssa.func @rotl_i32() -> i32 {
+// CHECK-LABEL: wasmssa.func public @rotl_i32() -> i32 {
 // CHECK:    %0 = wasmssa.const 10 : i32
 // CHECK:    %1 = wasmssa.const 3 : i32
 // CHECK:    %2 = wasmssa.rotl %0 by %1 bits : i32
 // CHECK:    wasmssa.return %2 : i32
 
-// CHECK-LABEL: wasmssa.func @rotl_i64() -> i64 {
+// CHECK-LABEL: wasmssa.func public @rotl_i64() -> i64 {
 // CHECK:    %0 = wasmssa.const 10 : i64
 // CHECK:    %1 = wasmssa.const 3 : i64
 // CHECK:    %2 = wasmssa.rotl %0 by %1 bits : i64
diff --git a/mlir/test/Target/Wasm/rotr.mlir b/mlir/test/Target/Wasm/rotr.mlir
index 5618b432693ad..4f57c151fda13 100644
--- a/mlir/test/Target/Wasm/rotr.mlir
+++ b/mlir/test/Target/Wasm/rotr.mlir
@@ -14,13 +14,13 @@
 )
 */
 
-// CHECK-LABEL: wasmssa.func @rotr_i32() -> i32 {
+// CHECK-LABEL: wasmssa.func public @rotr_i32() -> i32 {
 // CHECK:    %0 = wasmssa.const 10 : i32
 // CHECK:    %1 = wasmssa.const 3 : i32
 // CHECK:    %2 = wasmssa.rotr %0 by %1 bits : i32
 // CHECK:    wasmssa.return %2 : i32
 
-// CHECK-LABEL: wasmssa.func @rotr_i64() -> i64 {
+// CHECK-LABEL: wasmssa.func public @rotr_i64() -> i64 {
 // CHECK:    %0 = wasmssa.const 10 : i64
 // CHECK:    %1 = wasmssa.const 3 : i64
 // CHECK:    %2 = wasmssa.rotr %0 by %1 bits : i64
diff --git a/mlir/test/Target/Wasm/shl.mlir b/mlir/test/Target/Wasm/shl.mlir
index f2bdd573fab81..9762308effbaf 100644
--- a/mlir/test/Target/Wasm/shl.mlir
+++ b/mlir/test/Target/Wasm/shl.mlir
@@ -14,13 +14,13 @@
 )
 */
 
-// CHECK-LABEL: wasmssa.func @shl_i32() -> i32 {
+// CHECK-LABEL: wasmssa.func public @shl_i32() -> i32 {
 // CHECK:    %0 = wasmssa.const 10 : i32
 // CHECK:    %1 = wasmssa.const 3 : i32
 // CHECK:    %2 = wasmssa.shl %0 by %1 bits : i32
 // CHECK:    wasmssa.return %2 : i32
 
-// CHECK-LABEL: wasmssa.func @shl_i64() -> i64 {
+// CHECK-LABEL: wasmssa.func public @shl_i64() -> i64 {
 // CHECK:    %0 = wasmssa.const 10 : i64
 // CHECK:    %1 = wasmssa.const 3 : i64
 // CHECK:    %2 = wasmssa.shl %0 by %1 bits : i64
diff --git a/mlir/test/Target/Wasm/shr_s.mlir b/mlir/test/Target/Wasm/shr_s.mlir
index 247d9be28403c..942b5880a53e5 100644
--- a/mlir/test/Target/Wasm/shr_s.mlir
+++ b/mlir/test/Target/Wasm/shr_s.mlir
@@ -14,13 +14,13 @@
 )
 */
 
-// CHECK-LABEL: wasmssa.func @shr_s_i32() -> i32 {
+// CHECK-LABEL: wasmssa.func public @shr_s_i32() -> i32 {
 // CHECK:    %0 = wasmssa.const 10 : i32
 // CHECK:    %1 = wasmssa.const 3 : i32
 // CHECK:    %2 = wasmssa.shr_s %0 by %1 bits : i32
 // CHECK:    wasmssa.return %2 : i32
 
-// CHECK-LABEL: wasmssa.func @shr_s_i64() -> i64 {
+// CHECK-LABEL: wasmssa.func public @shr_s_i64() -> i64 {
 // CHECK:    %0 = wasmssa.const 10 : i64
 // CHECK:    %1 = wasmssa.const 3 : i64
 // CHECK:    %2 = wasmssa.shr_s %0 by %1 bits : i64
diff --git a/mlir/test/Target/Wasm/shr_u.mlir b/mlir/test/Target/Wasm/shr_u.mlir
index 9a79eed9b1d4a..6791262bd92e0 100644
--- a/mlir/test/Target/Wasm/shr_u.mlir
+++ b/mlir/test/Target/Wasm/shr_u.mlir
@@ -14,13 +14,13 @@
 )
 */
 
-// CHECK-LABEL: wasmssa.func @shr_u_i32() -> i32 {
+// CHECK-LABEL: wasmssa.func public @shr_u_i32() -> i32 {
 // CHECK:    %0 = wasmssa.const 10 : i32
 // CHECK:    %1 = wasmssa.const 3 : i32
 // CHECK:    %2 = wasmssa.shr_u %0 by %1 bits : i32
 // CHECK:    wasmssa.return %2 : i32
 
-// CHECK-LABEL: wasmssa.func @shr_u_i64() -> i64 {
+// CHECK-LABEL: wasmssa.func public @shr_u_i64() -> i64 {
 // CHECK:    %0 = wasmssa.const 10 : i64
 // CHECK:    %1 = wasmssa.const 3 : i64
 // CHECK:    %2 = wasmssa.shr_u %0 by %1 bits : i64
diff --git a/mlir/test/Target/Wasm/sqrt.mlir b/mlir/test/Target/Wasm/sqrt.mlir
index 77444ad69b16f..3ccf30b868ef1 100644
--- a/mlir/test/Target/Wasm/sqrt.mlir
+++ b/mlir/test/Target/Wasm/sqrt.mlir
@@ -12,12 +12,12 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @sqrt_f32() -> f32 {
+// CHECK-LABEL:   wasmssa.func public @sqrt_f32() -> f32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f32
 // CHECK:           %[[VAL_1:.*]] = wasmssa.sqrt %[[VAL_0]] : f32
 // CHECK:           wasmssa.return %[[VAL_1]] : f32
 
-// CHECK-LABEL:   wasmssa.func @sqrt_f64() -> f64 {
+// CHECK-LABEL:   wasmssa.func public @sqrt_f64() -> f64 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.const 1.000000e+01 : f64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.sqrt %[[VAL_0]] : f64
 // CHECK:           wasmssa.return %[[VAL_1]] : f64
diff --git a/mlir/test/Target/Wasm/wrap.mlir b/mlir/test/Target/Wasm/wrap.mlir
index 86ea0f7609d52..e2d226e36a6e0 100644
--- a/mlir/test/Target/Wasm/wrap.mlir
+++ b/mlir/test/Target/Wasm/wrap.mlir
@@ -8,7 +8,7 @@
 )
 */
 
-// CHECK-LABEL:   wasmssa.func @i64_wrap(
+// CHECK-LABEL:   wasmssa.func public @i64_wrap(
 // CHECK-SAME:      %[[ARG0:.*]]: !wasmssa<local ref to i64>) -> i32 {
 // CHECK:           %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] :  ref to i64
 // CHECK:           %[[VAL_1:.*]] = wasmssa.wrap %[[VAL_0]] : i64 to i32
diff --git a/mlir/test/Target/Wasm/xor.mlir b/mlir/test/Target/Wasm/xor.mlir
index 94691de2b3be4..3e7c481f1cf94 100644
--- a/mlir/test/Target/Wasm/xor.mlir
+++ b/mlir/test/Target/Wasm/xor.mlir
@@ -14,13 +14,13 @@
 )
 */
 
-// CHECK-LABEL: wasmssa.func @xor_i32() -> i32 {
+// CHECK-LABEL: wasmssa.func public @xor_i32() -> i32 {
 // CHECK:    %0 = wasmssa.const 10 : i32
 // CHECK:    %1 = wasmssa.const 3 : i32
 // CHECK:    %2 = wasmssa.xor %0 %1 : i32
 // CHECK:    wasmssa.return %2 : i32
 
-// CHECK-LABEL: wasmssa.func @xor_i64() -> i64 {
+// CHECK-LABEL: wasmssa.func public @xor_i64() -> i64 {
 // CHECK:    %0 = wasmssa.const 10 : i64
 // CHECK:    %1 = wasmssa.const 3 : i64
 // CHECK:    %2 = wasmssa.xor %0 %1 : i64



More information about the Mlir-commits mailing list