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

Oleksandr Alex Zinenko llvmlistbot at llvm.org
Fri Jul 18 06:11:26 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"> {
+  let summary = "Calling a wasm function";
+  let arguments = (ins FlatSymbolRefAttr: $callee,
+                       Variadic<WasmSSA_ValType>:  $operands);
+  let results = (outs Variadic<WasmSSA_ValType>: $results);
+  let assemblyFormat = "$callee (`(`$operands^`)`)? attr-dict `:` functional-type($operands, $results)";
+  let description = [{
+    Emits a call to callee.
+  }];
+}
+
+def WasmSSA_FuncImportOp : WasmSSA_Op<"import_func", [
+    Symbol,
+    CallableOpInterface,
+    WasmSSAImportOpInterface]> {
+  let summary = "Importing a function variable";
+  let arguments = (ins SymbolNameAttr: $sym_name,
+                     StrAttr: $moduleName,
+                     StrAttr: $importName,
+                     WasmSSA_FuncTypeAttr: $type,
+                     OptionalAttr<DictArrayAttr>:$arg_attrs,
+                     OptionalAttr<DictArrayAttr>:$res_attrs,
+                     OptionalAttr<StrAttr>:$sym_visibility);
+  let extraClassDeclaration = [{
+    bool isDeclaration() const { return true; }
+
+    Region *getCallableRegion() { return nullptr; }
+
+    llvm::ArrayRef<Type> getArgumentTypes() {
+      return getType().getInputs();
+    }
+
+    llvm::ArrayRef<Type> getResultTypes() {
+      return getType().getResults();
+    }
+  }];
+  let builders = [
+    OpBuilder<(ins "StringRef":$symbol,
+                   "StringRef":$moduleName,
+                   "StringRef":$importName,
+                   "FunctionType": $type)>
+  ];
+  let assemblyFormat = "$importName `from` $moduleName `as` $sym_name attr-dict";
+}
+
+def WasmSSA_GlobalOp : WasmSSA_Op<"global", [
+  AffineScope, AutomaticAllocationScope,
+  IsolatedFromAbove, Symbol, WasmSSAConstantExpressionInitializerInterface]> {
+  let summary= "WebAssembly global value";
+  let arguments = (ins SymbolNameAttr: $sym_name,
+                     WasmSSA_ValTypeAttr: $type,
+                     UnitAttr: $isMutable,
+                     OptionalAttr<StrAttr>:$sym_visibility);
+  let description = [{
+    WebAssembly global variable.
+    Body contains the initialization instructions for the variable value.
+  }];
+  let regions = (region AnyRegion: $initializer);
+
+  let builders = [
+    OpBuilder<(ins "StringRef":$symbol,
+                   "Type": $type,
+                   "bool": $isMutable)>
+  ];
+  let hasCustomAssemblyFormat = 1;
+}
+
+def WasmSSA_GlobalImportOp : WasmSSA_Op<"import_global", [
+    Symbol,
+    WasmSSAImportOpInterface]> {
+  let summary = "Importing a global variable";
+  let arguments = (ins SymbolNameAttr: $sym_name,
+                     StrAttr: $moduleName,
+                     StrAttr: $importName,
+                     WasmSSA_ValTypeAttr: $type,
+                     UnitAttr: $isMutable,
+                     OptionalAttr<StrAttr>:$sym_visibility);
+  let extraClassDeclaration = [{
+    bool isDeclaration() const { return true; }
+  }];
+  let builders = [
+    OpBuilder<(ins "StringRef":$symbol,
+                   "StringRef":$moduleName,
+                   "StringRef":$importName,
+                   "Type": $type,
+                   "bool": $isMutable)>
+  ];
+  let hasCustomAssemblyFormat = 1;
+}
+
+def WasmSSA_GlobalGetOp : WasmSSA_Op<"global_get", [DeclareOpInterfaceMethods<WasmSSAContextuallyConstantExprInterface>]> {
+  let summary = "Returns the value of the global passed as argument.";
+  let arguments = (ins FlatSymbolRefAttr: $global);
+  let results = (outs WasmSSA_ValType: $global_val);
+  let assemblyFormat = "$global attr-dict `:` type($global_val)";
+}
+
+def WasmSSA_IfOp : WasmSSA_Op<"if", [Terminator,
+    DeclareOpInterfaceMethods<WasmSSALabelLevelInterface>]> {
+  let summary = "Execute the if region if condition value is nonzero, the else region otherwise.";
+  let arguments = (ins I32:$condition, Variadic<WasmSSA_ValType>: $inputs);
+  let regions = (region AnyRegion: $if, AnyRegion: $else);
+  let successors = (successor AnySuccessor: $target);
+  let extraClassDeclaration = [{
+    private:
+    inline ::mlir::Block* createBlock(::mlir::Region& region) {
+      assert(region.empty() && "Creating entry block on non empty region");
+      assert(region.getParentOp() == this->getOperation() &&
+        "Creating block for region that isn't part of the current op");
+      auto &block = region.emplaceBlock();
+      for (auto input : getInputs())
+        block.addArgument(input.getType(), input.getLoc());
+      return █
+    }
+
+    public:
+    ::mlir::Block* createIfBlock() {
+      return createBlock(getIf());
+    }
+    ::mlir::Block* createElseBlock() {
+      return createBlock(getElse());
+    }
+  }];
+}
+
+def WasmSSA_LocalOp : WasmSSA_Op<"local", [
+    DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
+  let summary = "Declaration of local variable";
+  let arguments = (ins WasmSSA_ValTypeAttr: $type);
+  let results = (outs WasmSSA_LocalRef: $result);
+  let assemblyFormat = "`of` `type` $type attr-dict";
+}
+
+def WasmSSA_LocalGetOp : WasmSSA_Op<"local_get", [
+    DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
+  let summary = "Set local to value and return the operand.";
+  let arguments = (ins WasmSSA_LocalRef: $localVar);
+  let results = (outs WasmSSA_ValType: $result);
+  let assemblyFormat = "$localVar `:` type($localVar) attr-dict";
+  let hasVerifier = 1;
+}
+
+def WasmSSA_LocalSetOp : WasmSSA_Op<"local_set"> {
+  let summary = "Set local to given value";
+  let arguments = (ins WasmSSA_LocalRef: $localVar,
+                       WasmSSA_ValType: $value);
+  let hasVerifier = 1;
+  let assemblyFormat = "$localVar `:` type($localVar) `to` $value `:` type($value) attr-dict";
+}
+
+def WasmSSA_LocalTeeOp : WasmSSA_Op<"local_tee", [
+    DeclareOpInterfaceMethods<InferTypeOpInterface>]> {
+  let summary = "Set local to value and return the operand.";
+  let arguments = (ins WasmSSA_LocalRef: $localVar,
+                       WasmSSA_ValType: $value);
+  let results = (outs WasmSSA_ValType: $result);
+  let hasVerifier = 1;
+  let assemblyFormat = "$localVar `:` type($localVar) `to` $value `:` type($value) attr-dict";
+}
+
+def WasmSSA_MemOp : WasmSSA_Op<"memory", [Symbol]> {
+  let summary= "WebAssembly memory definition";
+  let arguments = (ins SymbolNameAttr: $sym_name,
+                     WasmSSA_LimitTypeAttr: $limits,
+                     OptionalAttr<StrAttr>:$sym_visibility);
+  let builders = [
+    OpBuilder<(ins
+    "llvm::StringRef":$symbol,
----------------
ftynse wrote:

```suggestion
    "::llvm::StringRef":$symbol,
```

there are some other cases, please check systematically

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


More information about the Mlir-commits mailing list