[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