[Mlir-commits] [mlir] [MLIR][Wasm] Introduce the WasmSSA MLIR dialect (PR #149233)

Ferdinand Lemaire llvmlistbot at llvm.org
Tue Jul 22 00:08:16 PDT 2025


================
@@ -0,0 +1,674 @@
+//===- WebAssemblySSAOps.td - WebAssemblySSA op definitions -*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef WEBASSEMBLYSSA_OPS
+#define WEBASSEMBLYSSA_OPS
+
+
+include "mlir/Dialect/WebAssemblySSA/IR/WebAssemblySSABase.td"
+include "mlir/Dialect/WebAssemblySSA/IR/WebAssemblySSATypes.td"
+include "mlir/Dialect/WebAssemblySSA/IR/WebAssemblySSAInterfaces.td"
+
+include "mlir/Interfaces/FunctionInterfaces.td"
+include "mlir/Interfaces/InferTypeOpInterface.td"
+include "mlir/IR/BuiltinAttributeInterfaces.td"
+include "mlir/IR/SymbolInterfaces.td"
+
+class WasmSSA_Op<string mnemonic, list<Trait> traits = []> :
+    Op<WasmSSA_Dialect, mnemonic, traits>;
+
+class WasmSSA_BlockLikeOp<string mnemonic, string summaryStr> :
+  WasmSSA_Op<mnemonic, [Terminator, DeclareOpInterfaceMethods<WasmSSALabelLevelInterface>]> {
+  let summary = summaryStr;
+  let arguments = (ins Variadic<WasmSSA_ValType>: $inputs);
+  let regions = (region AnyRegion: $body);
+  let successors = (successor AnySuccessor: $target);
+  let extraClassDeclaration = [{
+    ::mlir::Block* createBlock() {
+      auto &block = getBody().emplaceBlock();
+      for (auto input : getInputs())
+        block.addArgument(input.getType(), input.getLoc());
+      return █
+    }
+  }];
+  let assemblyFormat = "(`(`$inputs^`)` `:` type($inputs))? attr-dict  `:` $body `>` $target";
+}
+
+def WasmSSA_BlockOp : WasmSSA_BlockLikeOp<"block", "Create a nesting level"> {}
+
+def WasmSSA_LoopOp : WasmSSA_BlockLikeOp<"loop", "Create a nesting level similar to Block Op, except that it has itself as a successor."> {}
+
+def WasmSSA_BlockReturnOp : WasmSSA_Op<"block_return", [Terminator,
+    DeclareOpInterfaceMethods<WasmSSALabelBranchingInterface>]> {
+  let summary = "Return from the current block";
+  let arguments = (ins Variadic<WasmSSA_ValType>: $inputs);
+  let extraClassDeclaration = [{
+    ::mlir::Block* getTarget();
+  }];
+  let assemblyFormat = "($inputs^ `:` type($inputs))? attr-dict";
+}
+
+def WasmSSA_BranchIfOp : WasmSSA_Op<"branch_if", [
+    Terminator,
+    DeclareOpInterfaceMethods<WasmSSALabelBranchingInterface>]> {
+  let summary = "Jump to target level if condition has non-zero value";
+  let arguments = (ins I32: $condition,
+                       UI32Attr: $exitLevel,
+                       Variadic<WasmSSA_ValType>: $inputs);
+  let successors = (successor AnySuccessor: $elseSuccessor);
+  let assemblyFormat = "$condition `to` `level` $exitLevel (`with` `args`  `(`$inputs^ `:` type($inputs)`)`)?  `else` $elseSuccessor  attr-dict";
+}
+
+def WasmSSA_ConstOp : WasmSSA_Op<"const", [
+    AllTypesMatch<["value", "result"]>, WasmSSAConstantExprInterface]> {
+  let summary = "Operator that represents a constant value";
+  let arguments = (ins TypedAttrInterface: $value);
+  let results = (outs WasmSSA_NumericType: $result);
+  let assemblyFormat = "$value attr-dict";
+}
+
+def WasmSSA_FuncOp : WasmSSA_Op<"func", [
+    AffineScope, AutomaticAllocationScope,
+    DeclareOpInterfaceMethods<FunctionOpInterface>,
+    IsolatedFromAbove,
+    Symbol]> {
+  let description = [{
+    Represents a Wasm function definition.
+
+    In Wasm function, locals and function arguments are interchangeable.
+    They are for instance both accessed using `local.get` instruction.
+
+    On the other hand, a function type is defined as a pair of tuples of Wasm value types.
+    To model this, the wasm.func operation has:
+
+    - A function type that represents the corresponding wasm type (tuples of value types)
+
+    - Arguments of the entry block of type `!wasm<local T>`, with T the corresponding type
+     in the function type.
+  }];
+  let arguments = (ins SymbolNameAttr: $sym_name,
+                     WasmSSA_FuncTypeAttr: $functionType,
+                     OptionalAttr<DictArrayAttr>:$arg_attrs,
+                     OptionalAttr<DictArrayAttr>:$res_attrs,
+                     DefaultValuedAttr<StrAttr, "\"nested\"">:$sym_visibility);
+  let regions = (region AnyRegion: $body);
+  let extraClassDeclaration = [{
+
+    /// Create the entry block for the function with parameters wrapped in local ref.
+    ::mlir::Block* addEntryBlock();
+
+    //===------------------------------------------------------------------===//
+    // FunctionOpInterface Methods
+    //===------------------------------------------------------------------===//
+
+    /// Returns the region on the current operation that is callable. This may
+    /// return null in the case of an external callable object, e.g. an external
+    /// function.
+    ::mlir::Region *getCallableRegion() { return isExternal() ? nullptr : &getBody(); }
+
+    ::mlir::LogicalResult verifyBody();
+
+    /// Returns the argument types of this function.
+    ArrayRef<Type> getArgumentTypes() { return getFunctionType().getInputs(); }
+
+    /// Returns the result types of this function.
+    ArrayRef<Type> getResultTypes() { return getFunctionType().getResults(); }
+  }];
+
+  let builders = [
+    OpBuilder<(ins "llvm::StringRef":$symbol, "FunctionType":$funcType )>
+  ];
+  let hasCustomAssemblyFormat = 1;
+}
+
+def WasmSSA_FuncCallOp : WasmSSA_Op<"call"> {
----------------
flemairen6 wrote:

We thought about it but I think the interface implies the implementation of a bunch of functions we had no use for at the time so we left it as-is 


https://github.com/llvm/llvm-project/pull/149233


More information about the Mlir-commits mailing list