diff --git a/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td b/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td index b80ee2c38546a..e9425e884ae83 100644 --- a/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td +++ b/mlir/include/mlir/Dialect/WasmSSA/IR/WasmSSAOps.td @@ -43,9 +43,41 @@ class WasmSSA_BlockLikeOp : let assemblyFormat = "(`(`$inputs^`)` `:` type($inputs))? attr-dict `:` $body `>` $target"; } -def WasmSSA_BlockOp : WasmSSA_BlockLikeOp<"block", "Create a nesting level"> {} +def WasmSSA_BlockOp : WasmSSA_BlockLikeOp< + "block", + "Create a nesting level with a label at its exit."> { + let description = [{ + Defines a Wasm block, creating a new nested scope. + A block contains a body region and an optional list of input values. + Control can enter the block and later branch out to the block target. + Example: + + ```mlir + + wasmssa.block { + + // instructions + + } > ^successor + }]; +} + +def WasmSSA_LoopOp : WasmSSA_BlockLikeOp< + "loop", + "Create a nesting level that define its entry as jump target."> { + let description = [{ + Represents a Wasm loop construct. This defines a nesting level with + a label at the entry of the region. -def WasmSSA_LoopOp : WasmSSA_BlockLikeOp<"loop", "Create a nesting level similar to Block Op, except that it has itself as a successor."> {} + Example: + + ```mlir + + wasmssa.loop { + + } > ^successor + }]; +} def WasmSSA_BlockReturnOp : WasmSSA_Op<"block_return", [Terminator, DeclareOpInterfaceMethods]> { @@ -55,9 +87,16 @@ def WasmSSA_BlockReturnOp : WasmSSA_Op<"block_return", [Terminator, ::mlir::Block* getTarget(); }]; let description = [{ - Marks a return from the current block. + Escape from the current nesting level and return the control flow to its successor. + Optionally, mark the arguments that should be transfered to the successor block. - Example: + This shouldn't be confused with branch operations that targets the label defined + by the nesting level operation. + + For instance, a `wasmssa.block_return` in a loop will give back control to the + successor of the loop, where a `branch` targeting the loop will flow back to the entry block of the loop. + + Example: ```mlir wasmssa.block_return @@ -127,12 +166,18 @@ def WasmSSA_FuncOp : WasmSSA_Op<"func", [ - Arguments of the entry block of type `!wasm`, with T the corresponding type in the function type. + By default, `wasmssa.func` have nested visibility. Functions exported by the module + are marked with the exported attribute. This gives them public visibility. + Example: ```mlir - // A simple function with no arguments that returns a float32 + // Internal function with no arguments that returns a float32 wasmssa.func @my_f32_func() -> f32 + // Exported function with no arguments that returns a float32 + wasmssa.func exported @my_f32_func() -> f32 + // A function that takes a local ref argument wasmssa.func @i64_wrap(%a: !wasmssa) -> i32 ``` @@ -141,7 +186,7 @@ def WasmSSA_FuncOp : WasmSSA_Op<"func", [ WasmSSA_FuncTypeAttr: $functionType, OptionalAttr:$arg_attrs, OptionalAttr:$res_attrs, - DefaultValuedAttr:$sym_visibility); + UnitAttr: $exported); let regions = (region AnyRegion: $body); let extraClassDeclaration = [{ @@ -162,6 +207,12 @@ def WasmSSA_FuncOp : WasmSSA_Op<"func", [ /// Returns the result types of this function. ArrayRef getResultTypes() { return getFunctionType().getResults(); } + + ::mlir::SymbolTable::Visibility getVisibility() { + return getExported() ? + ::mlir::SymbolTable::Visibility::Public : + ::mlir::SymbolTable::Visibility::Nested; + }; }]; let builders = [ @@ -207,8 +258,7 @@ def WasmSSA_FuncImportOp : WasmSSA_Op<"import_func", [ StrAttr: $importName, WasmSSA_FuncTypeAttr: $type, OptionalAttr:$arg_attrs, - OptionalAttr:$res_attrs, - OptionalAttr:$sym_visibility); + OptionalAttr:$res_attrs); let extraClassDeclaration = [{ bool isDeclaration() const { return true; } @@ -221,6 +271,10 @@ def WasmSSA_FuncImportOp : WasmSSA_Op<"import_func", [ ::llvm::ArrayRef getResultTypes() { return getType().getResults(); } + + ::mlir::SymbolTable::Visibility getVisibility() { + return ::mlir::SymbolTable::Visibility::Nested; + }; }]; let builders = [ OpBuilder<(ins "StringRef":$symbol, @@ -238,30 +292,41 @@ def WasmSSA_GlobalOp : WasmSSA_Op<"global", [ let arguments = (ins SymbolNameAttr: $sym_name, WasmSSA_ValTypeAttr: $type, UnitAttr: $isMutable, - OptionalAttr:$sym_visibility); + UnitAttr: $exported); let description = [{ WebAssembly global variable. Body contains the initialization instructions for the variable value. The body must contain only instructions considered `const` in a webassembly context, such as `wasmssa.const` or `global.get`. + By default, `wasmssa.global` have nested visibility. Global exported by the module + are marked with the exported attribute. This gives them public visibility. + Example: ```mlir - // Define a global_var, a mutable i32 global variable equal to 10. - wasmssa.global @global_var i32 mutable nested : { + // Define module_global_var, an internal mutable i32 global variable equal to 10. + wasmssa.global @module_global_var i32 mutable : { %[[VAL_0:.*]] = wasmssa.const 10 : i32 wasmssa.return %[[VAL_0]] : i32 } + + // Define global_var, an exported constant i32 global variable equal to 42. + wasmssa.global @global_var i32 : { + %[[VAL_0:.*]] = wasmssa.const 42 : i32 + wasmssa.return %[[VAL_0]] : i32 + } ``` }]; let regions = (region AnyRegion: $initializer); - let builders = [ - OpBuilder<(ins "StringRef":$symbol, - "Type": $type, - "bool": $isMutable)> - ]; + let extraClassDeclaration = [{ + ::mlir::SymbolTable::Visibility getVisibility() { + return getExported() ? + ::mlir::SymbolTable::Visibility::Public : + ::mlir::SymbolTable::Visibility::Nested; + }; + }]; let hasCustomAssemblyFormat = 1; } @@ -283,18 +348,14 @@ def WasmSSA_GlobalImportOp : WasmSSA_Op<"import_global", [ StrAttr: $moduleName, StrAttr: $importName, WasmSSA_ValTypeAttr: $type, - UnitAttr: $isMutable, - OptionalAttr:$sym_visibility); + UnitAttr: $isMutable); let extraClassDeclaration = [{ bool isDeclaration() const { return true; } + + ::mlir::SymbolTable::Visibility getVisibility() { + return ::mlir::SymbolTable::Visibility::Nested; + }; }]; - let builders = [ - OpBuilder<(ins "StringRef":$symbol, - "StringRef":$moduleName, - "StringRef":$importName, - "Type": $type, - "bool": $isMutable)> - ]; let hasCustomAssemblyFormat = 1; } @@ -442,23 +503,33 @@ def WasmSSA_MemOp : WasmSSA_Op<"memory", [Symbol]> { Define a memory to be used by the program. Multiple memories can be defined in the same module. + By default, `wasmssa.memory` have nested visibility. Memory exported by + the module are marked with the exported attribute. This gives them public + visibility. + Example: ```mlir - // Define the `mem_0` memory with defined bounds of 0 -> 65536 + // Define the `mem_0` (internal) memory with defined size bounds of [0:65536] wasmssa.memory @mem_0 !wasmssa + + // Define the `mem_1` exported memory with minimal size of 512 + wasmssa.memory exported @mem_1 !wasmssa ``` }]; let arguments = (ins SymbolNameAttr: $sym_name, WasmSSA_LimitTypeAttr: $limits, - OptionalAttr:$sym_visibility); - let builders = [ - OpBuilder<(ins - "::llvm::StringRef":$symbol, - "wasmssa::LimitType":$limit)> - ]; + UnitAttr: $exported); - let assemblyFormat = "$sym_name custom($sym_visibility) $limits attr-dict"; + let extraClassDeclaration = [{ + ::mlir::SymbolTable::Visibility getVisibility() { + return getExported() ? + ::mlir::SymbolTable::Visibility::Public : + ::mlir::SymbolTable::Visibility::Nested; + }; + }]; + + let assemblyFormat = "(`exported` $exported^)? $sym_name $limits attr-dict"; } def WasmSSA_MemImportOp : WasmSSA_Op<"import_mem", [Symbol, ImportOpInterface]> { @@ -476,16 +547,13 @@ def WasmSSA_MemImportOp : WasmSSA_Op<"import_mem", [Symbol, ImportOpInterface]> let arguments = (ins SymbolNameAttr: $sym_name, StrAttr: $moduleName, StrAttr: $importName, - WasmSSA_LimitTypeAttr: $limits, - OptionalAttr:$sym_visibility); + WasmSSA_LimitTypeAttr: $limits); let extraClassDeclaration = [{ - bool isDeclaration() const { return true; } + bool isDeclaration() const { return true; } + ::mlir::SymbolTable::Visibility getVisibility() { + return ::mlir::SymbolTable::Visibility::Nested; + }; }]; - let builders = [OpBuilder<(ins - "::llvm::StringRef":$symbol, - "::llvm::StringRef":$moduleName, - "::llvm::StringRef":$importName, - "wasmssa::LimitType":$limits)>]; let assemblyFormat = "$importName `from` $moduleName `as` $sym_name attr-dict"; } @@ -493,11 +561,15 @@ def WasmSSA_TableOp : WasmSSA_Op<"table", [Symbol]> { let summary= "WebAssembly table value"; let arguments = (ins SymbolNameAttr: $sym_name, WasmSSA_TableTypeAttr: $type, - OptionalAttr:$sym_visibility); - let builders = [OpBuilder<(ins - "::llvm::StringRef":$symbol, - "wasmssa::TableType":$type)>]; - let assemblyFormat = "$sym_name custom($sym_visibility) $type attr-dict"; + UnitAttr: $exported); + let extraClassDeclaration = [{ + ::mlir::SymbolTable::Visibility getVisibility() { + return getExported() ? + ::mlir::SymbolTable::Visibility::Public : + ::mlir::SymbolTable::Visibility::Nested; + }; + }]; + let assemblyFormat = "(`exported` $exported^)? $sym_name $type attr-dict"; } def WasmSSA_TableImportOp : WasmSSA_Op<"import_table", [Symbol, ImportOpInterface]> { @@ -515,17 +587,14 @@ def WasmSSA_TableImportOp : WasmSSA_Op<"import_table", [Symbol, ImportOpInterfac let arguments = (ins SymbolNameAttr: $sym_name, StrAttr: $moduleName, StrAttr: $importName, - WasmSSA_TableTypeAttr: $type, - OptionalAttr:$sym_visibility); + WasmSSA_TableTypeAttr: $type); let extraClassDeclaration = [{ bool isDeclaration() const { return true; } + ::mlir::SymbolTable::Visibility getVisibility() { + return ::mlir::SymbolTable::Visibility::Nested; + }; }]; let assemblyFormat = "$importName `from` $moduleName `as` $sym_name attr-dict"; - let builders = [OpBuilder<(ins - "::llvm::StringRef":$symbol, - "::llvm::StringRef":$moduleName, - "::llvm::StringRef":$importName, - "wasmssa::TableType":$type)>]; } def WasmSSA_ReturnOp : WasmSSA_Op<"return", [Terminator]> { diff --git a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h index 21adde878994e..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}; @@ -29,6 +37,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}; @@ -93,6 +137,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/Dialect/WasmSSA/IR/WasmSSAOps.cpp b/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp index 89b62a21c4f52..a514ea9218bd7 100644 --- a/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp +++ b/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp @@ -12,6 +12,7 @@ #include "mlir/IR/Attributes.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/Diagnostics.h" #include "mlir/IR/Dialect.h" #include "mlir/IR/Region.h" #include "mlir/IR/SymbolTable.h" @@ -39,28 +40,6 @@ void printElseRegion(OpAsmPrinter &opPrinter, Operation *op, opPrinter.printKeywordOrString("else "); opPrinter.printRegion(elseRegion); } - -ParseResult parseWasmVisibility(OpAsmParser &opParser, StringAttr &visibility) { - std::string keyword; - auto initLocation = opParser.getCurrentLocation(); - std::ignore = opParser.parseOptionalKeywordOrString(&keyword); - if (keyword == "nested" or keyword == "") { - visibility = StringAttr::get(opParser.getContext(), "nested"); - return ParseResult::success(); - } - - if (keyword == "public" || keyword == "private") { - visibility = StringAttr::get(opParser.getContext(), keyword); - return ParseResult::success(); - } - opParser.emitError(initLocation, "expecting symbol visibility"); - return ParseResult::failure(); -} - -void printWasmVisibility(OpAsmPrinter &opPrinter, Operation *op, - Attribute visibility) { - opPrinter.printKeywordOrString(cast(visibility).strref()); -} } // namespace #define GET_OP_CLASSES @@ -167,10 +146,23 @@ Block *FuncOp::addEntryBlock() { void FuncOp::build(OpBuilder &odsBuilder, OperationState &odsState, StringRef symbol, FunctionType funcType) { - FuncOp::build(odsBuilder, odsState, symbol, funcType, {}, {}, "nested"); + FuncOp::build(odsBuilder, odsState, symbol, funcType, {}, {}); } ParseResult FuncOp::parse(OpAsmParser &parser, OperationState &result) { + auto *ctx = parser.getContext(); + std::string visibilityString; + auto loc = parser.getNameLoc(); + ParseResult res = parser.parseOptionalKeywordOrString(&visibilityString); + bool exported{false}; + if (res.succeeded()) { + if (visibilityString != "exported") + return parser.emitError( + loc, "expecting either `exported` or symbol name. got ") + << visibilityString; + exported = true; + } + auto buildFuncType = [&parser](Builder &builder, ArrayRef argTypes, ArrayRef results, function_interface_impl::VariadicFlag, @@ -191,11 +183,13 @@ ParseResult FuncOp::parse(OpAsmParser &parser, OperationState &result) { return builder.getFunctionType(argTypesWithoutLocal, results); }; - - return function_interface_impl::parseFunctionOp( + auto funcParseRes = function_interface_impl::parseFunctionOp( parser, result, /*allowVariadic=*/false, getFunctionTypeAttrName(result.name), buildFuncType, getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name)); + if (exported) + result.addAttribute(getExportedAttrName(result.name), UnitAttr::get(ctx)); + return funcParseRes; } LogicalResult FuncOp::verifyBody() { @@ -224,9 +218,18 @@ LogicalResult FuncOp::verifyBody() { } void FuncOp::print(OpAsmPrinter &p) { + /// If exported, print it before and mask it before printing + /// using generic interface. + auto exported = getExported(); + if (exported) { + p << " exported"; + removeExportedAttr(); + } function_interface_impl::printFunctionOp( p, *this, /*isVariadic=*/false, getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName()); + if (exported) + setExported(true); } //===----------------------------------------------------------------------===// @@ -237,38 +240,37 @@ void FuncImportOp::build(OpBuilder &odsBuilder, OperationState &odsState, StringRef symbol, StringRef moduleName, StringRef importName, FunctionType type) { FuncImportOp::build(odsBuilder, odsState, symbol, moduleName, importName, - type, {}, {}, odsBuilder.getStringAttr("nested")); + type, {}, {}); } //===----------------------------------------------------------------------===// // GlobalOp //===----------------------------------------------------------------------===// - -void GlobalOp::build(OpBuilder &odsBuilder, OperationState &odsState, - StringRef symbol, Type type, bool isMutable) { - GlobalOp::build(odsBuilder, odsState, symbol, type, isMutable, - odsBuilder.getStringAttr("nested")); -} - // Custom formats ParseResult GlobalOp::parse(OpAsmParser &parser, OperationState &result) { StringAttr symbolName; Type globalType; auto *ctx = parser.getContext(); - ParseResult res = parser.parseSymbolName( - symbolName, SymbolTable::getSymbolAttrName(), result.attributes); + std::string visibilityString; + auto loc = parser.getNameLoc(); + ParseResult res = parser.parseOptionalKeywordOrString(&visibilityString); + if (res.succeeded()) { + if (visibilityString != "exported") + return parser.emitError( + loc, "expecting either `exported` or symbol name. got ") + << visibilityString; + result.addAttribute(getExportedAttrName(result.name), UnitAttr::get(ctx)); + } + res = parser.parseSymbolName(symbolName, SymbolTable::getSymbolAttrName(), + result.attributes); res = parser.parseType(globalType); result.addAttribute(getTypeAttrName(result.name), TypeAttr::get(globalType)); std::string mutableString; res = parser.parseOptionalKeywordOrString(&mutableString); if (res.succeeded() && mutableString == "mutable") result.addAttribute("isMutable", UnitAttr::get(ctx)); - std::string visibilityString; - res = parser.parseOptionalKeywordOrString(&visibilityString); - if (res.succeeded()) - result.addAttribute("sym_visibility", - StringAttr::get(ctx, visibilityString)); + res = parser.parseColon(); Region *globalInitRegion = result.addRegion(); res = parser.parseRegion(*globalInitRegion); @@ -276,11 +278,11 @@ ParseResult GlobalOp::parse(OpAsmParser &parser, OperationState &result) { } void GlobalOp::print(OpAsmPrinter &printer) { + if (getExported()) + printer << " exported"; printer << " @" << getSymName().str() << " " << getType(); if (getIsMutable()) printer << " mutable"; - if (auto vis = getSymVisibility()) - printer << " " << *vis; printer << " :"; Region &body = getRegion(); if (!body.empty()) { @@ -319,13 +321,6 @@ GlobalGetOp::verifySymbolUses(SymbolTableCollection &symbolTable) { // GlobalImportOp //===----------------------------------------------------------------------===// -void GlobalImportOp::build(OpBuilder &odsBuilder, OperationState &odsState, - StringRef symbol, StringRef moduleName, - StringRef importName, Type type, bool isMutable) { - GlobalImportOp::build(odsBuilder, odsState, symbol, moduleName, importName, - type, isMutable, odsBuilder.getStringAttr("nested")); -} - ParseResult GlobalImportOp::parse(OpAsmParser &parser, OperationState &result) { auto *ctx = parser.getContext(); ParseResult res = parseImportOp(parser, result); @@ -335,12 +330,8 @@ ParseResult GlobalImportOp::parse(OpAsmParser &parser, OperationState &result) { res = parser.parseOptionalKeywordOrString(&mutableOrSymVisString); if (res.succeeded() && mutableOrSymVisString == "mutable") { result.addAttribute("isMutable", UnitAttr::get(ctx)); - res = parser.parseOptionalKeywordOrString(&mutableOrSymVisString); } - if (res.succeeded()) - result.addAttribute("sym_visibility", - StringAttr::get(ctx, mutableOrSymVisString)); res = parser.parseColon(); Type importedType; @@ -356,8 +347,6 @@ void GlobalImportOp::print(OpAsmPrinter &printer) { << "\" as @" << getSymName(); if (getIsMutable()) printer << " mutable"; - if (auto vis = getSymVisibility()) - printer << " " << *vis; printer << " : " << getType(); } @@ -430,27 +419,6 @@ LogicalResult LocalTeeOp::verify() { Block *LoopOp::getLabelTarget() { return &getBody().front(); } -//===----------------------------------------------------------------------===// -// MemOp -//===----------------------------------------------------------------------===// - -void MemOp::build(OpBuilder &odsBuilder, OperationState &odsState, - StringRef symbol, LimitType limit) { - MemOp::build(odsBuilder, odsState, symbol, limit, - odsBuilder.getStringAttr("nested")); -} - -//===----------------------------------------------------------------------===// -// MemImportOp -//===----------------------------------------------------------------------===// - -void MemImportOp::build(OpBuilder &odsBuilder, OperationState &odsState, - StringRef symbol, StringRef moduleName, - StringRef importName, LimitType limits) { - MemImportOp::build(odsBuilder, odsState, symbol, moduleName, importName, - limits, odsBuilder.getStringAttr("nested")); -} - //===----------------------------------------------------------------------===// // ReinterpretOp //===----------------------------------------------------------------------===// @@ -471,24 +439,3 @@ LogicalResult ReinterpretOp::verify() { //===----------------------------------------------------------------------===// void ReturnOp::build(OpBuilder &odsBuilder, OperationState &odsState) {} - -//===----------------------------------------------------------------------===// -// TableOp -//===----------------------------------------------------------------------===// - -void TableOp::build(OpBuilder &odsBuilder, OperationState &odsState, - StringRef symbol, TableType type) { - TableOp::build(odsBuilder, odsState, symbol, type, - odsBuilder.getStringAttr("nested")); -} - -//===----------------------------------------------------------------------===// -// TableImportOp -//===----------------------------------------------------------------------===// - -void TableImportOp::build(OpBuilder &odsBuilder, OperationState &odsState, - StringRef symbol, StringRef moduleName, - StringRef importName, TableType type) { - TableImportOp::build(odsBuilder, odsState, symbol, moduleName, importName, - type, odsBuilder.getStringAttr("nested")); -} diff --git a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp index 6afbe0505e649..5e998394722e0 100644 --- a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp +++ b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp @@ -14,6 +14,7 @@ #include "mlir/IR/Attributes.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinAttributeInterfaces.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Location.h" #include "mlir/Support/LLVM.h" @@ -138,6 +139,10 @@ using ImportDesc = using parsed_inst_t = FailureOr>; +struct EmptyBlockMarker {}; +using BlockTypeParseResult = + std::variant; + struct WasmModuleSymbolTables { SmallVector funcSymbols; SmallVector globalSymbols; @@ -175,6 +180,9 @@ class ParserHead; /// Wrapper around SmallVector to only allow access as push and pop on the /// stack. Makes sure that there are no "free accesses" on the stack to preserve /// its state. +/// This class also keep tracks of the Wasm labels defined by different ops, +/// which can be targeted by control flow ops. This can be modeled as part of +/// the Value Stack as Wasm control flow ops can only target enclosing labels. class ValueStack { private: struct LabelLevel { @@ -206,6 +214,16 @@ class ValueStack { /// if an error occurs. LogicalResult pushResults(ValueRange results, Location *opLoc); + void addLabelLevel(LabelLevelOpInterface levelOp) { + labelLevel.push_back({values.size(), levelOp}); + LDBG() << "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 +232,7 @@ class ValueStack { private: SmallVector values; + SmallVector labelLevel; }; using local_val_t = TypedValue; @@ -248,6 +267,19 @@ class ExpressionParser { buildNumericOp(OpBuilder &builder, std::enable_if_t> * = 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 + 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. @@ -280,11 +312,105 @@ class ExpressionParser { } } + /// + /// RAII guard class for creating a nesting level + /// + struct NestingContextGuard { + NestingContextGuard(ExpressionParser &parser, LabelLevelOpInterface levelOp) + : parser{parser} { + parser.addNestingContextLevel(levelOp); + } + NestingContextGuard(NestingContextGuard &&other) : parser{other.parser} { + other.shouldDropOnDestruct = false; + } + NestingContextGuard(NestingContextGuard const &) = delete; + ~NestingContextGuard() { + 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 getFuncTypeFor(OpBuilder &builder, + EmptyBlockMarker) { + return builder.getFunctionType({}, {}); + } + + llvm::FailureOr 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 getFuncTypeFor(OpBuilder &builder, + Type valType) { + return builder.getFunctionType({}, {valType}); + } + + llvm::FailureOr + getFuncTypeFor(OpBuilder &builder, BlockTypeParseResult parseResult) { + return std::visit( + [this, &builder](auto value) { return getFuncTypeFor(builder, value); }, + parseResult); + } + + llvm::FailureOr + getFuncTypeFor(OpBuilder &builder, + llvm::FailureOr parseResult) { + if (llvm::failed(parseResult)) + return failure(); + return getFuncTypeFor(builder, *parseResult); + } + + llvm::FailureOr parseBlockFuncType(OpBuilder &builder); + struct ParseResultWithInfo { SmallVector opResults; std::byte endingByte; }; + template > + /// @param blockToFill: the block which content will be populated + /// @param resType: the type that this block is supposed to return + llvm::FailureOr + parseBlockContent(OpBuilder &builder, Block *blockToFill, TypeRange resTypes, + Location opLoc, LabelLevelOpInterface levelOp, + FilterT parseEndBytes = {}) { + OpBuilder::InsertionGuard guard{builder}; + builder.setInsertionPointToStart(blockToFill); + LDBG() << "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(opLoc, *returnOperands); + LDBG() << "end of parsing of a block"; + return bodyParsingRes->endingByte; + } + public: template parsed_inst_t parse(OpBuilder &builder, UniqueByte = {}); @@ -294,7 +420,11 @@ class ExpressionParser { parse(OpBuilder &builder, ByteSequence parsingEndFilters); - FailureOr> popOperands(TypeRange operandTypes) { + NestingContextGuard addNesting(LabelLevelOpInterface levelOp) { + return NestingContextGuard{*this, levelOp}; + } + + FailureOr> popOperands(TypeRange operandTypes) { return valueStack.popOperands(operandTypes, ¤tOpLoc.value()); } @@ -308,6 +438,12 @@ class ExpressionParser { template 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 + parsed_inst_t parseBlockLikeOp(OpBuilder &); + private: std::optional currentOpLoc; ParserHead &parser; @@ -586,6 +722,29 @@ class ParserHead { return success(); } + llvm::FailureOr 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::max()) + return emitError(loc, "type ID should be representable with an unsigned " + "32 bits integer. Got ") + << *typeIdx; + return {TypeIdxRecord{static_cast(*typeIdx)}}; + } + bool end() const { return curHead().empty(); } ParserHead copy() const { return *this; } @@ -701,17 +860,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() << "" << "\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> { + 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; ++idx) { 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() << "" << "\n"; llvm::dbgs() << "=========================================================\n"; @@ -726,7 +909,7 @@ parsed_inst_t ValueStack::popOperands(TypeRange operandTypes, Location *opLoc) { return emitError(*opLoc, "stack doesn't contain enough values. trying to get ") << operandTypes.size() << " operands on a stack containing only " - << values.size() << " values."; + << values.size() << " values"; size_t stackIdxOffset = values.size() - operandTypes.size(); SmallVector res{}; res.reserve(operandTypes.size()); @@ -735,8 +918,7 @@ parsed_inst_t ValueStack::popOperands(TypeRange operandTypes, Location *opLoc) { Type stackType = operand.getType(); if (stackType != operandTypes[i]) return emitError(*opLoc, "invalid operand type on stack. expecting ") - << operandTypes[i] << ", value on stack is of type " << stackType - << "."; + << operandTypes[i] << ", value on stack is of type " << stackType; LDBG() << " POP: " << operand; res.push_back(operand); } @@ -792,6 +974,151 @@ ExpressionParser::parse(OpBuilder &builder, } } +llvm::FailureOr +ExpressionParser::parseBlockFuncType(OpBuilder &builder) { + return getFuncTypeFor(builder, parser.parseBlockType(builder.getContext())); +} + +template +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 locations{}; + locations.resize(resTypes.size(), *currentOpLoc); + auto *successor = + builder.createBlock(curRegion, curRegion->end(), resTypes, locations); + builder.setInsertionPointToEnd(curBlock); + auto blockOp = + builder.create(*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( + OpBuilder &builder) { + return parseBlockLikeOp(builder); +} + +template <> +inline parsed_inst_t +ExpressionParser::parseSpecificInstruction( + OpBuilder &builder) { + return parseBlockLikeOp(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(); + + LDBG() << "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 locations{}; + locations.resize(resTypes.size(), *currentOpLoc); + auto *successor = + builder.createBlock(curRegion, curRegion->end(), resTypes, locations); + builder.setInsertionPointToEnd(curBlock); + auto ifOp = builder.create(*currentOpLoc, conditionValue->front(), + *inputOps, successor); + auto *ifEntryBlock = ifOp.createIfBlock(); + constexpr auto ifElseFilter = + ByteSequence{}; + 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(); + 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(*currentOpLoc, condition->front(), + builder.getUI32IntegerAttr(*level), *branchArgs, + elseBlock); + builder.setInsertionPointToStart(elseBlock); + return {*branchArgs}; +} + +template <> +inline parsed_inst_t +ExpressionParser::parseSpecificInstruction( + OpBuilder &builder) { + auto loc = *currentOpLoc; + auto funcIdx = parser.parseLiteral(); + if (failed(funcIdx)) + return failure(); + if (*funcIdx >= symbols.funcSymbols.size()) + return emitError(loc, "Invalid function index: ") << *funcIdx; + auto callee = symbols.funcSymbols[*funcIdx]; + llvm::ArrayRef inTypes = callee.functionType.getInputs(); + llvm::ArrayRef resTypes = callee.functionType.getResults(); + parsed_inst_t inOperands = popOperands(inTypes); + if (failed(inOperands)) + return failure(); + auto callOp = + builder.create(loc, resTypes, callee.symbol, *inOperands); + return {callOp.getResults()}; +} + template <> inline parsed_inst_t ExpressionParser::parseSpecificInstruction< WasmBinaryEncoding::OpCode::localGet>(OpBuilder &builder) { @@ -834,7 +1161,7 @@ parsed_inst_t ExpressionParser::parseSetOrTee(OpBuilder &builder) { if (valueStack.empty()) return emitError( *currentOpLoc, - "invalid stack access, trying to access a value on an empty stack."); + "invalid stack access, trying to access a value on an empty stack"); parsed_inst_t poppedOp = popOperands(locals[*id].getType().getElementType()); if (failed(poppedOp)) @@ -1000,11 +1327,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 +1354,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 +1366,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. @@ -1036,6 +1378,105 @@ BUILD_NUMERIC_UNARY_OP_INT(PopCntOp, popcnt) #undef BUILD_NUMERIC_OP #undef BUILD_NUMERIC_CAST_OP +template +inline parsed_inst_t ExpressionParser::buildConvertOp(OpBuilder &builder, + extraArgsT... extraArgs) { + static_assert(std::is_arithmetic_v, + "InputType should be an arithmetic type"); + static_assert(std::is_arithmetic_v, + "OutputType should be an arithmetic type"); + auto intype = buildLiteralType(builder); + auto outType = buildLiteralType(builder); + auto operand = popOperands(intype); + if (failed(operand)) + return failure(); + auto op = builder.create(*currentOpLoc, outType, operand->front(), + extraArgs...); + LDBG() << "Built operation: " << op; + return {{op.getResult()}}; +} + +template <> +inline parsed_inst_t ExpressionParser::parseSpecificInstruction< + WasmBinaryEncoding::OpCode::demoteF64ToF32>(OpBuilder &builder) { + return buildConvertOp(builder); +} + +template <> +inline parsed_inst_t +ExpressionParser::parseSpecificInstruction( + OpBuilder &builder) { + return buildConvertOp(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(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(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(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(builder); \ + } \ + \ + template <> \ + inline parsed_inst_t ExpressionParser::parseSpecificInstruction< \ + WasmBinaryEncoding::OpCode::reinterpretI##WIDTH##AsF##WIDTH>(OpBuilder & \ + builder) { \ + return buildConvertOp(builder); \ + } + +BUILD_REINTERPRET_PARSER(32, float) +BUILD_REINTERPRET_PARSER(64, double) + +#undef BUILD_REINTERPRET_PARSER + class WasmBinaryParser { private: struct SectionRegistry { @@ -1153,7 +1594,7 @@ class WasmBinaryParser { if (tid.id >= symbols.moduleFuncTypes.size()) return emitError(loc, "invalid type id: ") << tid.id << ". Only " << symbols.moduleFuncTypes.size() - << " type registration."; + << " type registrations"; FunctionType type = symbols.moduleFuncTypes[tid.id]; std::string symbol = symbols.getNewFuncSymbolName(); auto funcOp = FuncImportOp::create(builder, loc, symbol, moduleName, @@ -1221,7 +1662,7 @@ class WasmBinaryParser { FileLineColLoc magicLoc = parser.getLocation(); FailureOr magic = parser.consumeNBytes(wasmHeader.size()); if (failed(magic) || magic->compare(wasmHeader)) { - emitError(magicLoc, "source file does not contain valid Wasm header."); + emitError(magicLoc, "source file does not contain valid Wasm header"); return; } auto const expectedVersionString = StringRef{"\1\0\0\0", 4}; @@ -1391,7 +1832,7 @@ WasmBinaryParser::parseSectionItem(ParserHead &ph, return failure(); Operation *op = SymbolTable::lookupSymbolIn(mOp, *currentSymbol); - SymbolTable::setSymbolVisibility(op, SymbolTable::Visibility::Public); + op->setAttr("exported", UnitAttr::get(op->getContext())); StringAttr symName = SymbolTable::getSymbolName(op); return SymbolTable{mOp}.rename(symName, *exportName); } diff --git a/mlir/test/Dialect/WasmSSA/custom_parser/global.mlir b/mlir/test/Dialect/WasmSSA/custom_parser/global.mlir index b9b342052ff1b..a25abbd2a8662 100644 --- a/mlir/test/Dialect/WasmSSA/custom_parser/global.mlir +++ b/mlir/test/Dialect/WasmSSA/custom_parser/global.mlir @@ -1,7 +1,7 @@ // RUN: mlir-opt %s | FileCheck %s module { - wasmssa.import_global "from_js" from "env" as @global_0 nested : i32 + wasmssa.import_global "from_js" from "env" as @global_0 : i32 wasmssa.global @global_1 i32 : { %0 = wasmssa.const 10 : i32 @@ -21,7 +21,7 @@ module { } } -// CHECK-LABEL: wasmssa.import_global "from_js" from "env" as @global_0 nested : i32 +// CHECK-LABEL: wasmssa.import_global "from_js" from "env" as @global_0 : i32 // CHECK-LABEL: wasmssa.global @global_1 i32 : { // CHECK: %[[VAL_0:.*]] = wasmssa.const 10 : i32 diff --git a/mlir/test/Dialect/WasmSSA/custom_parser/if.mlir b/mlir/test/Dialect/WasmSSA/custom_parser/if.mlir index 01068cbe94fc2..cee3c695af2f0 100644 --- a/mlir/test/Dialect/WasmSSA/custom_parser/if.mlir +++ b/mlir/test/Dialect/WasmSSA/custom_parser/if.mlir @@ -1,6 +1,6 @@ // RUN: mlir-opt %s | FileCheck %s -// CHECK-LABEL: wasmssa.func nested @func_0( +// CHECK-LABEL: wasmssa.func @func_0( // CHECK-SAME: %[[ARG0:.*]]: !wasmssa) -> i32 { // CHECK: %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32 // CHECK: wasmssa.if %[[VAL_0]] : { @@ -12,7 +12,7 @@ // CHECK: }> ^bb1 // CHECK: ^bb1(%[[VAL_3:.*]]: f32): // CHECK: wasmssa.return %[[VAL_3]] : f32 -wasmssa.func nested @func_0(%arg0 : !wasmssa) -> i32 { +wasmssa.func @func_0(%arg0 : !wasmssa) -> i32 { %cond = wasmssa.local_get %arg0 : ref to i32 wasmssa.if %cond : { %c0 = wasmssa.const 0.5 : f32 @@ -25,7 +25,7 @@ wasmssa.func nested @func_0(%arg0 : !wasmssa) -> i32 { wasmssa.return %retVal : f32 } -// CHECK-LABEL: wasmssa.func nested @func_1( +// CHECK-LABEL: wasmssa.func @func_1( // CHECK-SAME: %[[ARG0:.*]]: !wasmssa) -> i32 { // CHECK: %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32 // CHECK: %[[VAL_1:.*]] = wasmssa.local of type i32 @@ -38,7 +38,7 @@ wasmssa.func nested @func_0(%arg0 : !wasmssa) -> i32 { // CHECK: ^bb1: // CHECK: %[[VAL_4:.*]] = wasmssa.local_get %[[VAL_1]] : ref to i32 // CHECK: wasmssa.return %[[VAL_4]] : i32 -wasmssa.func nested @func_1(%arg0 : !wasmssa) -> i32 { +wasmssa.func @func_1(%arg0 : !wasmssa) -> i32 { %cond = wasmssa.local_get %arg0 : ref to i32 %var = wasmssa.local of type i32 %zero = wasmssa.const 0 diff --git a/mlir/test/Dialect/WasmSSA/custom_parser/import.mlir b/mlir/test/Dialect/WasmSSA/custom_parser/import.mlir index 3cc05486c4a4d..dc232299afadd 100644 --- a/mlir/test/Dialect/WasmSSA/custom_parser/import.mlir +++ b/mlir/test/Dialect/WasmSSA/custom_parser/import.mlir @@ -5,13 +5,13 @@ module { wasmssa.import_func "bar" from "my_module" as @func_1 {sym_visibility = "nested", type = (i32) -> ()} wasmssa.import_table "table" from "my_module" as @table_0 {sym_visibility = "nested", type = !wasmssa} wasmssa.import_mem "mem" from "my_module" as @mem_0 {limits = !wasmssa, sym_visibility = "nested"} - wasmssa.import_global "glob" from "my_module" as @global_0 nested : i32 - wasmssa.import_global "glob_mut" from "my_other_module" as @global_1 mutable nested : i32 + wasmssa.import_global "glob" from "my_module" as @global_0 : i32 + wasmssa.import_global "glob_mut" from "my_other_module" as @global_1 mutable : i32 } // CHECK-LABEL: wasmssa.import_func "foo" from "my_module" as @func_0 {sym_visibility = "nested", type = (i32) -> ()} // CHECK: wasmssa.import_func "bar" from "my_module" as @func_1 {sym_visibility = "nested", type = (i32) -> ()} // CHECK: wasmssa.import_table "table" from "my_module" as @table_0 {sym_visibility = "nested", type = !wasmssa} // CHECK: wasmssa.import_mem "mem" from "my_module" as @mem_0 {limits = !wasmssa, sym_visibility = "nested"} -// CHECK: wasmssa.import_global "glob" from "my_module" as @global_0 nested : i32 -// CHECK: wasmssa.import_global "glob_mut" from "my_other_module" as @global_1 mutable nested : i32 +// CHECK: wasmssa.import_global "glob" from "my_module" as @global_0 : i32 +// CHECK: wasmssa.import_global "glob_mut" from "my_other_module" as @global_1 mutable : i32 diff --git a/mlir/test/Dialect/WasmSSA/custom_parser/local.mlir b/mlir/test/Dialect/WasmSSA/custom_parser/local.mlir index 3f6423fa2a1f5..f613ebf07be1d 100644 --- a/mlir/test/Dialect/WasmSSA/custom_parser/local.mlir +++ b/mlir/test/Dialect/WasmSSA/custom_parser/local.mlir @@ -1,7 +1,7 @@ // RUN: mlir-opt %s | FileCheck %s module { - wasmssa.func nested @func_0() -> f32 { + wasmssa.func @func_0() -> f32 { %0 = wasmssa.local of type f32 %1 = wasmssa.local of type f32 %2 = wasmssa.const 8.000000e+00 : f32 @@ -9,7 +9,7 @@ module { %4 = wasmssa.add %2 %3 : f32 wasmssa.return %4 : f32 } - wasmssa.func nested @func_1() -> i32 { + wasmssa.func @func_1() -> i32 { %0 = wasmssa.local of type i32 %1 = wasmssa.local of type i32 %2 = wasmssa.const 8 : i32 @@ -17,13 +17,13 @@ module { %4 = wasmssa.add %2 %3 : i32 wasmssa.return %4 : i32 } - wasmssa.func nested @func_2(%arg0: !wasmssa) -> i32 { + wasmssa.func @func_2(%arg0: !wasmssa) -> i32 { %0 = wasmssa.const 3 : i32 wasmssa.return %0 : i32 } } -// CHECK-LABEL: wasmssa.func nested @func_0() -> f32 { +// CHECK-LABEL: wasmssa.func @func_0() -> f32 { // CHECK: %[[VAL_0:.*]] = wasmssa.local of type f32 // CHECK: %[[VAL_1:.*]] = wasmssa.local of type f32 // CHECK: %[[VAL_2:.*]] = wasmssa.const 8.000000e+00 : f32 @@ -31,7 +31,7 @@ module { // CHECK: %[[VAL_4:.*]] = wasmssa.add %[[VAL_2]] %[[VAL_3]] : f32 // CHECK: wasmssa.return %[[VAL_4]] : f32 -// CHECK-LABEL: wasmssa.func nested @func_1() -> i32 { +// CHECK-LABEL: wasmssa.func @func_1() -> i32 { // CHECK: %[[VAL_0:.*]] = wasmssa.local of type i32 // CHECK: %[[VAL_1:.*]] = wasmssa.local of type i32 // CHECK: %[[VAL_2:.*]] = wasmssa.const 8 : i32 @@ -39,7 +39,7 @@ module { // CHECK: %[[VAL_4:.*]] = wasmssa.add %[[VAL_2]] %[[VAL_3]] : i32 // CHECK: wasmssa.return %[[VAL_4]] : i32 -// CHECK-LABEL: wasmssa.func nested @func_2( +// CHECK-LABEL: wasmssa.func @func_2( // CHECK-SAME: %[[ARG0:.*]]: !wasmssa) -> i32 { // CHECK: %[[VAL_0:.*]] = wasmssa.const 3 : i32 // CHECK: wasmssa.return %[[VAL_0]] : i32 diff --git a/mlir/test/Dialect/WasmSSA/custom_parser/memory.mlir b/mlir/test/Dialect/WasmSSA/custom_parser/memory.mlir index 47551dbf18292..ca6ebe01b1f7e 100644 --- a/mlir/test/Dialect/WasmSSA/custom_parser/memory.mlir +++ b/mlir/test/Dialect/WasmSSA/custom_parser/memory.mlir @@ -1,7 +1,7 @@ // RUN: mlir-opt %s | FileCheck %s -// CHECK: wasmssa.memory @mem0 public !wasmssa -wasmssa.memory @mem0 public !wasmssa - -// CHECK: wasmssa.memory @mem1 nested !wasmssa +// CHECK: wasmssa.memory @mem1 !wasmssa wasmssa.memory @mem1 !wasmssa + +// CHECK: wasmssa.memory exported @mem2 !wasmssa +wasmssa.memory exported @mem2 !wasmssa diff --git a/mlir/test/Dialect/WasmSSA/custom_parser/table.mlir b/mlir/test/Dialect/WasmSSA/custom_parser/table.mlir index 5a874f4ac9e08..ea630deaff69c 100644 --- a/mlir/test/Dialect/WasmSSA/custom_parser/table.mlir +++ b/mlir/test/Dialect/WasmSSA/custom_parser/table.mlir @@ -1,7 +1,7 @@ // RUN: mlir-opt %s | FileCheck %s -// CHECK: wasmssa.table @tab0 public !wasmssa -wasmssa.table @tab0 public !wasmssa +// CHECK: wasmssa.table exported @tab0 !wasmssa +wasmssa.table exported @tab0 !wasmssa -// CHECK: wasmssa.table @tab1 nested !wasmssa +// CHECK: wasmssa.table @tab1 !wasmssa wasmssa.table @tab1 !wasmssa diff --git a/mlir/test/Dialect/WasmSSA/extend-invalid.mlir b/mlir/test/Dialect/WasmSSA/extend-invalid.mlir index 8d782801c33f9..7687e5f32f799 100644 --- a/mlir/test/Dialect/WasmSSA/extend-invalid.mlir +++ b/mlir/test/Dialect/WasmSSA/extend-invalid.mlir @@ -1,7 +1,7 @@ // RUN: mlir-opt %s -split-input-file -verify-diagnostics -wasmssa.func nested @extend_low_64() -> i32 { +wasmssa.func @extend_low_64() -> i32 { %0 = wasmssa.const 10 : i32 // expected-error@+1 {{extend op can only take 8, 16 or 32 bits. Got 64}} %1 = wasmssa.extend 64 low bits from %0: i32 @@ -10,7 +10,7 @@ wasmssa.func nested @extend_low_64() -> i32 { // ----- -wasmssa.func nested @extend_too_much() -> i32 { +wasmssa.func @extend_too_much() -> i32 { %0 = wasmssa.const 10 : i32 // expected-error@+1 {{trying to extend the 32 low bits from a 'i32' value is illegal}} %1 = wasmssa.extend 32 low bits from %0: i32 diff --git a/mlir/test/Dialect/WasmSSA/global-invalid.mlir b/mlir/test/Dialect/WasmSSA/global-invalid.mlir index b9cafd8b900bf..c5bc606fd13f3 100644 --- a/mlir/test/Dialect/WasmSSA/global-invalid.mlir +++ b/mlir/test/Dialect/WasmSSA/global-invalid.mlir @@ -13,7 +13,7 @@ module { // ----- module { - wasmssa.import_global "glob" from "my_module" as @global_0 mutable nested : i32 + wasmssa.import_global "glob" from "my_module" as @global_0 mutable : i32 wasmssa.global @global_1 i32 : { // expected-error@+1 {{global.get op is considered constant if it's referring to a import.global symbol marked non-mutable}} %0 = wasmssa.global_get @global_0 : i32 @@ -30,3 +30,13 @@ module { wasmssa.return %0 : i32 } } + +// ----- + +module { + // expected-error@+1 {{expecting either `exported` or symbol name. got exproted}} + wasmssa.global exproted @global_1 i32 : { + %0 = wasmssa.const 17 : i32 + wasmssa.return %0 : i32 + } +} diff --git a/mlir/test/Dialect/WasmSSA/locals-invalid.mlir b/mlir/test/Dialect/WasmSSA/locals-invalid.mlir index 35c590b36b289..eaad80e19584d 100644 --- a/mlir/test/Dialect/WasmSSA/locals-invalid.mlir +++ b/mlir/test/Dialect/WasmSSA/locals-invalid.mlir @@ -1,6 +1,6 @@ // RUN: mlir-opt %s -split-input-file -verify-diagnostics -wasmssa.func nested @local_set_err(%arg0: !wasmssa) -> i64 { +wasmssa.func @local_set_err(%arg0: !wasmssa) -> i64 { %0 = wasmssa.const 3 : i64 // expected-error@+1 {{input type and result type of local.set do not match}} wasmssa.local_set %arg0 : ref to i32 to %0 : i64 @@ -9,7 +9,7 @@ wasmssa.func nested @local_set_err(%arg0: !wasmssa) -> i64 { // ----- -wasmssa.func nested @local_tee_err(%arg0: !wasmssa) -> i32 { +wasmssa.func @local_tee_err(%arg0: !wasmssa) -> i32 { %0 = wasmssa.const 3 : i64 // expected-error@+1 {{input type and output type of local.tee do not match}} %1 = wasmssa.local_tee %arg0 : ref to i32 to %0 : i64 diff --git a/mlir/test/Target/Wasm/abs.mlir b/mlir/test/Target/Wasm/abs.mlir index 9c45ba78507ad..fe3602a521698 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 exported @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 exported @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..8a87c6084892d --- /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 {type = (i32) -> i32} + +// CHECK-LABEL: wasmssa.func exported @add( +// CHECK-SAME: %[[ARG0:.*]]: !wasmssa, +// CHECK-SAME: %[[ARG1:.*]]: !wasmssa) -> 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 exported @memory !wasmssa + +// CHECK-LABEL: wasmssa.global @global_0 i32 mutable : { +// 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..323d41a522bab 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 exported @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 exported @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..c85fc1e12d647 --- /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 exported @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..67df1983687ef --- /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 @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..fa30f08274956 --- /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 @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..c91ff37555478 --- /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 @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..c0169aa238794 --- /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 @func_0() -> i32 { +// CHECK: %[[VAL_0:.*]] = wasmssa.const 42 : i32 +// CHECK: wasmssa.return %[[VAL_0]] : i32 + +// CHECK-LABEL: wasmssa.func exported @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..858c09da6d8df 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 exported @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 exported @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/comparison_ops.mlir b/mlir/test/Target/Wasm/comparison_ops.mlir new file mode 100644 index 0000000000000..91e3a6a0f6fc8 --- /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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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 @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/const.mlir b/mlir/test/Target/Wasm/const.mlir index aa9e76f8502b6..adb792a70e3fe 100644 --- a/mlir/test/Target/Wasm/const.mlir +++ b/mlir/test/Target/Wasm/const.mlir @@ -16,22 +16,22 @@ ) */ -// CHECK-LABEL: wasmssa.func nested @func_0() -> i32 { +// CHECK-LABEL: wasmssa.func @func_0() -> i32 { // CHECK: %[[VAL_0:.*]] = wasmssa.const 1 : i32 // CHECK: wasmssa.return %[[VAL_0]] : i32 // CHECK: } -// CHECK-LABEL: wasmssa.func nested @func_1() -> i64 { +// CHECK-LABEL: wasmssa.func @func_1() -> i64 { // CHECK: %[[VAL_0:.*]] = wasmssa.const 3 : i64 // CHECK: wasmssa.return %[[VAL_0]] : i64 // CHECK: } -// CHECK-LABEL: wasmssa.func nested @func_2() -> f32 { +// CHECK-LABEL: wasmssa.func @func_2() -> f32 { // CHECK: %[[VAL_0:.*]] = wasmssa.const 4.000000e+00 : f32 // CHECK: wasmssa.return %[[VAL_0]] : f32 // CHECK: } -// CHECK-LABEL: wasmssa.func nested @func_3() -> f64 { +// CHECK-LABEL: wasmssa.func @func_3() -> f64 { // CHECK: %[[VAL_0:.*]] = wasmssa.const 9.000000e+00 : f64 // CHECK: wasmssa.return %[[VAL_0]] : f64 // CHECK: } diff --git a/mlir/test/Target/Wasm/convert.mlir b/mlir/test/Target/Wasm/convert.mlir new file mode 100644 index 0000000000000..ddc29a798af28 --- /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 exported @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 exported @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 exported @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 exported @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 exported @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 exported @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 exported @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 exported @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..90c5b119e9265 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 exported @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 exported @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..9e7cc5ef93e91 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 exported @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 exported @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/demote.mlir b/mlir/test/Target/Wasm/demote.mlir new file mode 100644 index 0000000000000..3d2bc05b17609 --- /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 @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/div.mlir b/mlir/test/Target/Wasm/div.mlir index c91f7809a255d..4967d96971f2a 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 exported @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 exported @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 exported @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 exported @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 exported @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 exported @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 exported @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 exported @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 exported @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 exported @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..8b3e4997e63e1 --- /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 @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..5c98f1a2676c7 --- /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 @func_0( +// CHECK-SAME: %[[ARG0:.*]]: !wasmssa) { +// 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 @func_1( +// CHECK-SAME: %[[ARG0:.*]]: !wasmssa) { +// 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/eq.mlir b/mlir/test/Target/Wasm/eq.mlir new file mode 100644 index 0000000000000..ba3ae2f759c2f --- /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 @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 @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 @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 @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..55cf94adc92e0 --- /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 exported @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 exported @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/extend.mlir b/mlir/test/Target/Wasm/extend.mlir new file mode 100644 index 0000000000000..5d4446ac62c81 --- /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 @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 @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 @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 @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 @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 @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 @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/global.mlir b/mlir/test/Target/Wasm/global.mlir index e72fe69666999..1e4fe44742de7 100644 --- a/mlir/test/Target/Wasm/global.mlir +++ b/mlir/test/Target/Wasm/global.mlir @@ -29,9 +29,9 @@ i32.add ) */ -// CHECK-LABEL: wasmssa.import_global "from_js" from "env" as @global_0 nested : i32 +// CHECK-LABEL: wasmssa.import_global "from_js" from "env" as @global_0 : i32 -// CHECK-LABEL: wasmssa.func nested @func_0() -> i32 { +// CHECK-LABEL: wasmssa.func @func_0() -> i32 { // CHECK: %[[VAL_0:.*]] = wasmssa.global_get @global_0 : i32 // CHECK: %[[VAL_1:.*]] = wasmssa.global_get @global_1 : i32 // CHECK: %[[VAL_2:.*]] = wasmssa.add %[[VAL_0]] %[[VAL_1]] : i32 @@ -41,26 +41,26 @@ i32.add // CHECK: %[[VAL_6:.*]] = wasmssa.add %[[VAL_2]] %[[VAL_5]] : i32 // CHECK: wasmssa.return %[[VAL_6]] : i32 -// CHECK-LABEL: wasmssa.global @global_1 i32 nested : { +// CHECK-LABEL: wasmssa.global @global_1 i32 : { // CHECK: %[[VAL_0:.*]] = wasmssa.const 10 : i32 // CHECK: wasmssa.return %[[VAL_0]] : i32 -// CHECK-LABEL: wasmssa.global @global_2 i32 mutable nested : { +// CHECK-LABEL: wasmssa.global @global_2 i32 mutable : { // CHECK: %[[VAL_0:.*]] = wasmssa.const 10 : i32 // CHECK: wasmssa.return %[[VAL_0]] : i32 -// CHECK-LABEL: wasmssa.global @global_3 i32 mutable nested : { +// CHECK-LABEL: wasmssa.global @global_3 i32 mutable : { // CHECK: %[[VAL_0:.*]] = wasmssa.const 10 : i32 // CHECK: wasmssa.return %[[VAL_0]] : i32 -// CHECK-LABEL: wasmssa.global @global_4 i64 nested : { +// CHECK-LABEL: wasmssa.global @global_4 i64 : { // CHECK: %[[VAL_0:.*]] = wasmssa.const 11 : i64 // CHECK: wasmssa.return %[[VAL_0]] : i64 -// CHECK-LABEL: wasmssa.global @global_5 f32 nested : { +// CHECK-LABEL: wasmssa.global @global_5 f32 : { // CHECK: %[[VAL_0:.*]] = wasmssa.const 1.200000e+01 : f32 // CHECK: wasmssa.return %[[VAL_0]] : f32 -// CHECK-LABEL: wasmssa.global @global_6 f64 nested : { +// CHECK-LABEL: wasmssa.global @global_6 f64 : { // CHECK: %[[VAL_0:.*]] = wasmssa.const 1.300000e+01 : f64 // CHECK: wasmssa.return %[[VAL_0]] : f64 diff --git a/mlir/test/Target/Wasm/if.mlir b/mlir/test/Target/Wasm/if.mlir new file mode 100644 index 0000000000000..2d7bfbed6f754 --- /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 @func_0( +// CHECK-SAME: %[[ARG0:.*]]: !wasmssa) -> 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 @func_1( +// CHECK-SAME: %[[ARG0:.*]]: !wasmssa) -> 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 @func_2( +// CHECK-SAME: %[[ARG0:.*]]: !wasmssa) -> 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/import.mlir b/mlir/test/Target/Wasm/import.mlir index 541dcf3a2d9eb..dcdfa52703539 100644 --- a/mlir/test/Target/Wasm/import.mlir +++ b/mlir/test/Target/Wasm/import.mlir @@ -11,9 +11,9 @@ ) */ -// CHECK-LABEL: wasmssa.import_func "foo" from "my_module" as @func_0 {sym_visibility = "nested", type = (i32) -> ()} -// CHECK: wasmssa.import_func "bar" from "my_module" as @func_1 {sym_visibility = "nested", type = (i32) -> ()} -// CHECK: wasmssa.import_table "table" from "my_module" as @table_0 {sym_visibility = "nested", type = !wasmssa} -// CHECK: wasmssa.import_mem "mem" from "my_module" as @mem_0 {limits = !wasmssa, sym_visibility = "nested"} -// CHECK: wasmssa.import_global "glob" from "my_module" as @global_0 nested : i32 -// CHECK: wasmssa.import_global "glob_mut" from "my_other_module" as @global_1 mutable nested : i32 +// CHECK-LABEL: wasmssa.import_func "foo" from "my_module" as @func_0 {type = (i32) -> ()} +// CHECK: wasmssa.import_func "bar" from "my_module" as @func_1 {type = (i32) -> ()} +// CHECK: wasmssa.import_table "table" from "my_module" as @table_0 {type = !wasmssa} +// CHECK: wasmssa.import_mem "mem" from "my_module" as @mem_0 {limits = !wasmssa} +// CHECK: wasmssa.import_global "glob" from "my_module" as @global_0 : i32 +// CHECK: wasmssa.import_global "glob_mut" from "my_other_module" as @global_1 mutable : 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/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/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/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/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/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/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/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/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/invalid_block_type_index.yaml b/mlir/test/Target/Wasm/invalid_block_type_index.yaml new file mode 100644 index 0000000000000..5b83e2e32c8a2 --- /dev/null +++ b/mlir/test/Target/Wasm/invalid_block_type_index.yaml @@ -0,0 +1,28 @@ + +# RUN: yaml2obj %s | not mlir-translate --import-wasm -o - 2>&1 | FileCheck %s + +# CHECK: type index references nonexistent type (2) + +--- !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: 410E020241016A0B0B +# -----------------------------^^ Invalid type ID diff --git a/mlir/test/Target/Wasm/local.mlir b/mlir/test/Target/Wasm/local.mlir index 32f590021b959..9844f9c64a212 100644 --- a/mlir/test/Target/Wasm/local.mlir +++ b/mlir/test/Target/Wasm/local.mlir @@ -29,7 +29,7 @@ ) */ -// CHECK-LABEL: wasmssa.func nested @func_0() -> f32 { +// CHECK-LABEL: wasmssa.func @func_0() -> f32 { // CHECK: %[[VAL_0:.*]] = wasmssa.local of type f32 // CHECK: %[[VAL_1:.*]] = wasmssa.local of type f32 // CHECK: %[[VAL_2:.*]] = wasmssa.const 8.000000e+00 : f32 @@ -40,7 +40,7 @@ // CHECK: %[[VAL_6:.*]] = wasmssa.add %[[VAL_3]] %[[VAL_5]] : f32 // CHECK: wasmssa.return %[[VAL_6]] : f32 -// CHECK-LABEL: wasmssa.func nested @func_1() -> i32 { +// CHECK-LABEL: wasmssa.func @func_1() -> i32 { // CHECK: %[[VAL_0:.*]] = wasmssa.local of type i32 // CHECK: %[[VAL_1:.*]] = wasmssa.local of type i32 // CHECK: %[[VAL_2:.*]] = wasmssa.const 8 : i32 @@ -51,7 +51,7 @@ // CHECK: %[[VAL_6:.*]] = wasmssa.add %[[VAL_3]] %[[VAL_5]] : i32 // CHECK: wasmssa.return %[[VAL_6]] : i32 -// CHECK-LABEL: wasmssa.func nested @func_2( +// CHECK-LABEL: wasmssa.func @func_2( // CHECK-SAME: %[[ARG0:.*]]: !wasmssa) -> i32 { // CHECK: %[[VAL_0:.*]] = wasmssa.const 3 : i32 // CHECK: wasmssa.local_set %[[ARG0]] : ref to i32 to %[[VAL_0]] : i32 diff --git a/mlir/test/Target/Wasm/loop.mlir b/mlir/test/Target/Wasm/loop.mlir new file mode 100644 index 0000000000000..29ad5026772b8 --- /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 @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..311d007226516 --- /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 @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..9160bde7779bb 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 exported @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 exported @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/memory_min_eq_max.mlir b/mlir/test/Target/Wasm/memory_min_eq_max.mlir index 2ba5ab50d51fa..ea8f71948200f 100644 --- a/mlir/test/Target/Wasm/memory_min_eq_max.mlir +++ b/mlir/test/Target/Wasm/memory_min_eq_max.mlir @@ -4,4 +4,4 @@ (module (memory 0 0)) */ -// CHECK-LABEL: wasmssa.memory @mem_0 nested !wasmssa +// CHECK-LABEL: wasmssa.memory @mem_0 !wasmssa diff --git a/mlir/test/Target/Wasm/memory_min_max.mlir b/mlir/test/Target/Wasm/memory_min_max.mlir index ebf64189189f8..88782eca2b96c 100644 --- a/mlir/test/Target/Wasm/memory_min_max.mlir +++ b/mlir/test/Target/Wasm/memory_min_max.mlir @@ -4,4 +4,4 @@ (module (memory 0 65536)) */ -// CHECK-LABEL: wasmssa.memory @mem_0 nested !wasmssa +// CHECK-LABEL: wasmssa.memory @mem_0 !wasmssa diff --git a/mlir/test/Target/Wasm/memory_min_no_max.mlir b/mlir/test/Target/Wasm/memory_min_no_max.mlir index 8d8878618bcc0..c10c5ccef3b6d 100644 --- a/mlir/test/Target/Wasm/memory_min_no_max.mlir +++ b/mlir/test/Target/Wasm/memory_min_no_max.mlir @@ -4,4 +4,4 @@ (module (memory 1)) */ -// CHECK-LABEL: wasmssa.memory @mem_0 nested !wasmssa +// CHECK-LABEL: wasmssa.memory @mem_0 !wasmssa diff --git a/mlir/test/Target/Wasm/min.mlir b/mlir/test/Target/Wasm/min.mlir index 1058c7d32be71..2372bcc8d25b6 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 exported @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 exported @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/ne.mlir b/mlir/test/Target/Wasm/ne.mlir new file mode 100644 index 0000000000000..331df757f1934 --- /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 @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 @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 @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 @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 diff --git a/mlir/test/Target/Wasm/neg.mlir b/mlir/test/Target/Wasm/neg.mlir index 5811ab50348bd..dae8ee58767fc 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 exported @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 exported @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..be0b3d7c89173 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 exported @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 exported @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..bfaa8ebaee996 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 exported @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 exported @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/promote.mlir b/mlir/test/Target/Wasm/promote.mlir new file mode 100644 index 0000000000000..44c31b60548a2 --- /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 @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..574d13f8d3f45 --- /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 exported @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 exported @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 exported @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 exported @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..16c9c78d04e00 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 exported @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 exported @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 exported @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 exported @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..4c2e5af22c477 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 exported @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 exported @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..ec403d0e36e4d 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 exported @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 exported @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/rounding.mlir b/mlir/test/Target/Wasm/rounding.mlir new file mode 100644 index 0000000000000..947637eb8aa27 --- /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 @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 @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 @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 @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 @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 @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/shl.mlir b/mlir/test/Target/Wasm/shl.mlir index f2bdd573fab81..1363112377695 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 exported @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 exported @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..da1a38f6397f6 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 exported @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 exported @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..2991c2a724cb6 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 exported @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 exported @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..6b968d6b9ff1a 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 exported @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 exported @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/sub.mlir b/mlir/test/Target/Wasm/sub.mlir index b9c6caf006583..5b242f433a5ea 100644 --- a/mlir/test/Target/Wasm/sub.mlir +++ b/mlir/test/Target/Wasm/sub.mlir @@ -27,25 +27,25 @@ ) */ -// CHECK-LABEL: wasmssa.func nested @func_0() -> i32 { +// CHECK-LABEL: wasmssa.func @func_0() -> i32 { // CHECK: %[[VAL_0:.*]] = wasmssa.const 12 : i32 // CHECK: %[[VAL_1:.*]] = wasmssa.const 50 : i32 // CHECK: %[[VAL_2:.*]] = wasmssa.sub %[[VAL_0]] %[[VAL_1]] : i32 // CHECK: wasmssa.return %[[VAL_2]] : i32 -// CHECK-LABEL: wasmssa.func nested @func_1() -> i64 { +// CHECK-LABEL: wasmssa.func @func_1() -> i64 { // CHECK: %[[VAL_0:.*]] = wasmssa.const 20 : i64 // CHECK: %[[VAL_1:.*]] = wasmssa.const 5 : i64 // CHECK: %[[VAL_2:.*]] = wasmssa.sub %[[VAL_0]] %[[VAL_1]] : i64 // CHECK: wasmssa.return %[[VAL_2]] : i64 -// CHECK-LABEL: wasmssa.func nested @func_2() -> f32 { +// CHECK-LABEL: wasmssa.func @func_2() -> f32 { // CHECK: %[[VAL_0:.*]] = wasmssa.const 5.000000e+00 : f32 // CHECK: %[[VAL_1:.*]] = wasmssa.const 1.400000e+01 : f32 // CHECK: %[[VAL_2:.*]] = wasmssa.sub %[[VAL_0]] %[[VAL_1]] : f32 // CHECK: wasmssa.return %[[VAL_2]] : f32 -// CHECK-LABEL: wasmssa.func nested @func_3() -> f64 { +// CHECK-LABEL: wasmssa.func @func_3() -> f64 { // CHECK: %[[VAL_0:.*]] = wasmssa.const 1.700000e+01 : f64 // CHECK: %[[VAL_1:.*]] = wasmssa.const 0.000000e+00 : f64 // CHECK: %[[VAL_2:.*]] = wasmssa.sub %[[VAL_0]] %[[VAL_1]] : f64 diff --git a/mlir/test/Target/Wasm/wrap.mlir b/mlir/test/Target/Wasm/wrap.mlir new file mode 100644 index 0000000000000..1266758c56594 --- /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 exported @i64_wrap( +// CHECK-SAME: %[[ARG0:.*]]: !wasmssa) -> 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 diff --git a/mlir/test/Target/Wasm/xor.mlir b/mlir/test/Target/Wasm/xor.mlir index 94691de2b3be4..56407db501c0d 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 exported @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 exported @xor_i64() -> i64 { // CHECK: %0 = wasmssa.const 10 : i64 // CHECK: %1 = wasmssa.const 3 : i64 // CHECK: %2 = wasmssa.xor %0 %1 : i64