[MLIR][WASM] Control flow, conversion and comparison in Wasm importer (#154674)

This is the following of PR #154452.

It extend Wasm binary to Wasm SSA importer with support of control flow
operations, comparison operations and conversion operations.

---------

Co-authored-by: Ferdinand Lemaire <ferdinand.lemaire@woven-planet.global>
Co-authored-by: Jessica Paquette <jessica.paquette@woven-planet.global>
Co-authored-by: Luc Forget <luc.forget@woven.toyota>
This commit is contained in:
Luc Forget
2025-10-17 20:43:30 +09:00
committed by GitHub
parent 993e80d846
commit e40f215573
85 changed files with 2633 additions and 263 deletions

View File

@@ -43,9 +43,41 @@ class WasmSSA_BlockLikeOp<string mnemonic, string summaryStr> :
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:
def WasmSSA_LoopOp : WasmSSA_BlockLikeOp<"loop", "Create a nesting level similar to Block Op, except that it has itself as a successor."> {}
```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.
Example:
```mlir
wasmssa.loop {
} > ^successor
}];
}
def WasmSSA_BlockReturnOp : WasmSSA_Op<"block_return", [Terminator,
DeclareOpInterfaceMethods<LabelBranchingOpInterface>]> {
@@ -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<local T>`, 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<local ref to i64>) -> i32
```
@@ -141,7 +186,7 @@ def WasmSSA_FuncOp : WasmSSA_Op<"func", [
WasmSSA_FuncTypeAttr: $functionType,
OptionalAttr<DictArrayAttr>:$arg_attrs,
OptionalAttr<DictArrayAttr>:$res_attrs,
DefaultValuedAttr<StrAttr, "\"nested\"">:$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<Type> 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<DictArrayAttr>:$arg_attrs,
OptionalAttr<DictArrayAttr>:$res_attrs,
OptionalAttr<StrAttr>:$sym_visibility);
OptionalAttr<DictArrayAttr>:$res_attrs);
let extraClassDeclaration = [{
bool isDeclaration() const { return true; }
@@ -221,6 +271,10 @@ def WasmSSA_FuncImportOp : WasmSSA_Op<"import_func", [
::llvm::ArrayRef<Type> 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<StrAttr>:$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<StrAttr>:$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<limit[0:65536]>
// Define the `mem_1` exported memory with minimal size of 512
wasmssa.memory exported @mem_1 !wasmssa<limit[512:]>
```
}];
let arguments = (ins SymbolNameAttr: $sym_name,
WasmSSA_LimitTypeAttr: $limits,
OptionalAttr<StrAttr>:$sym_visibility);
let builders = [
OpBuilder<(ins
"::llvm::StringRef":$symbol,
"wasmssa::LimitType":$limit)>
];
UnitAttr: $exported);
let assemblyFormat = "$sym_name custom<WasmVisibility>($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<StrAttr>:$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<StrAttr>:$sym_visibility);
let builders = [OpBuilder<(ins
"::llvm::StringRef":$symbol,
"wasmssa::TableType":$type)>];
let assemblyFormat = "$sym_name custom<WasmVisibility>($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<StrAttr>:$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]> {

View File

@@ -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

View File

@@ -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<StringAttr>(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<Type> argTypes,
ArrayRef<Type> 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"));
}

View File

@@ -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<SmallVector<Value>>;
struct EmptyBlockMarker {};
using BlockTypeParseResult =
std::variant<EmptyBlockMarker, TypeIdxRecord, Type>;
struct WasmModuleSymbolTables {
SmallVector<FunctionSymbolRefContainer> funcSymbols;
SmallVector<GlobalSymbolRefContainer> 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 @@ public:
/// 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 @@ public:
private:
SmallVector<Value> values;
SmallVector<LabelLevel> labelLevel;
};
using local_val_t = TypedValue<wasmssa::LocalRefType>;
@@ -248,6 +267,19 @@ private:
buildNumericOp(OpBuilder &builder,
std::enable_if_t<std::is_arithmetic_v<valueType>> * = nullptr);
/// Construct a conversion operation of type \p opType that takes a value from
/// type \p inputType on the stack and will produce a value of type
/// \p outputType.
///
/// \p opType - The WASM dialect operation to build.
/// \p inputType - The operand type for the built instruction.
/// \p outputType - The result type for the built instruction.
///
/// \returns The parsed instruction result, or failure.
template <typename opType, typename inputType, typename outputType,
typename... extraArgsT>
inline parsed_inst_t buildConvertOp(OpBuilder &builder, extraArgsT...);
/// This function generates a dispatch tree to associate an opcode with a
/// parser. Parsers are registered by specialising the
/// `parseSpecificInstruction` function for the op code to handle.
@@ -280,11 +312,105 @@ private:
}
}
///
/// 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<FunctionType> getFuncTypeFor(OpBuilder &builder,
EmptyBlockMarker) {
return builder.getFunctionType({}, {});
}
llvm::FailureOr<FunctionType> getFuncTypeFor(OpBuilder &builder,
TypeIdxRecord type) {
if (type.id >= symbols.moduleFuncTypes.size())
return emitError(*currentOpLoc,
"type index references nonexistent type (")
<< type.id << "). Only " << symbols.moduleFuncTypes.size()
<< " types are registered";
return symbols.moduleFuncTypes[type.id];
}
llvm::FailureOr<FunctionType> getFuncTypeFor(OpBuilder &builder,
Type valType) {
return builder.getFunctionType({}, {valType});
}
llvm::FailureOr<FunctionType>
getFuncTypeFor(OpBuilder &builder, BlockTypeParseResult parseResult) {
return std::visit(
[this, &builder](auto value) { return getFuncTypeFor(builder, value); },
parseResult);
}
llvm::FailureOr<FunctionType>
getFuncTypeFor(OpBuilder &builder,
llvm::FailureOr<BlockTypeParseResult> parseResult) {
if (llvm::failed(parseResult))
return failure();
return getFuncTypeFor(builder, *parseResult);
}
llvm::FailureOr<FunctionType> parseBlockFuncType(OpBuilder &builder);
struct ParseResultWithInfo {
SmallVector<Value> opResults;
std::byte endingByte;
};
template <typename FilterT = ByteSequence<WasmBinaryEncoding::endByte>>
/// @param blockToFill: the block which content will be populated
/// @param resType: the type that this block is supposed to return
llvm::FailureOr<std::byte>
parseBlockContent(OpBuilder &builder, Block *blockToFill, TypeRange resTypes,
Location opLoc, LabelLevelOpInterface levelOp,
FilterT parseEndBytes = {}) {
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<BlockReturnOp>(opLoc, *returnOperands);
LDBG() << "end of parsing of a block";
return bodyParsingRes->endingByte;
}
public:
template <std::byte ParseEndByte = WasmBinaryEncoding::endByte>
parsed_inst_t parse(OpBuilder &builder, UniqueByte<ParseEndByte> = {});
@@ -294,7 +420,11 @@ public:
parse(OpBuilder &builder,
ByteSequence<ExpressionParseEnd...> parsingEndFilters);
FailureOr<SmallVector<Value>> popOperands(TypeRange operandTypes) {
NestingContextGuard addNesting(LabelLevelOpInterface levelOp) {
return NestingContextGuard{*this, levelOp};
}
FailureOr<llvm::SmallVector<Value>> popOperands(TypeRange operandTypes) {
return valueStack.popOperands(operandTypes, &currentOpLoc.value());
}
@@ -308,6 +438,12 @@ public:
template <typename OpToCreate>
parsed_inst_t parseSetOrTee(OpBuilder &);
/// Blocks and Loops have a similar format and differ only in how their exit
/// is handled which doesn´t matter at parsing time. Factorizes in one
/// function.
template <typename OpToCreate>
parsed_inst_t parseBlockLikeOp(OpBuilder &);
private:
std::optional<Location> currentOpLoc;
ParserHead &parser;
@@ -586,6 +722,29 @@ public:
return success();
}
llvm::FailureOr<BlockTypeParseResult> parseBlockType(MLIRContext *ctx) {
auto loc = getLocation();
auto blockIndicator = peek();
if (failed(blockIndicator))
return failure();
if (*blockIndicator == WasmBinaryEncoding::Type::emptyBlockType) {
offset += 1;
return {EmptyBlockMarker{}};
}
if (isValueOneOf(*blockIndicator, valueTypesEncodings))
return parseValueType(ctx);
/// Block type idx is a 32 bit positive integer encoded as a 33 bit signed
/// value
auto typeIdx = parseI64();
if (failed(typeIdx))
return failure();
if (*typeIdx < 0 || *typeIdx > std::numeric_limits<uint32_t>::max())
return emitError(loc, "type ID should be representable with an unsigned "
"32 bits integer. Got ")
<< *typeIdx;
return {TypeIdxRecord{static_cast<uint32_t>(*typeIdx)}};
}
bool end() const { return curHead().empty(); }
ParserHead copy() const { return *this; }
@@ -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() << "<Top>"
<< "\n";
// Stack is pushed to via push_back. Therefore the top of the stack is the
// end of the vector. Iterate in reverse so that the first thing we print
// is the top of the stack.
auto indexGetter = [this]() {
size_t idx = labelLevel.size();
return [this, idx]() mutable -> std::optional<std::pair<size_t, size_t>> {
llvm::dbgs() << "IDX: " << idx << '\n';
if (idx == 0)
return std::nullopt;
auto frameId = idx - 1;
auto frameLimit = labelLevel[frameId].stackIdx;
idx -= 1;
return {{frameId, frameLimit}};
};
};
auto getNextFrameIndex = indexGetter();
auto nextFrameIdx = getNextFrameIndex();
size_t stackSize = size();
for (size_t idx = 0; idx < stackSize; idx++) {
for (size_t idx = 0; idx < stackSize; ++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() << "<Bottom>"
<< "\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<Value> 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<FunctionType>
ExpressionParser::parseBlockFuncType(OpBuilder &builder) {
return getFuncTypeFor(builder, parser.parseBlockType(builder.getContext()));
}
template <typename OpToCreate>
parsed_inst_t ExpressionParser::parseBlockLikeOp(OpBuilder &builder) {
auto opLoc = currentOpLoc;
auto funcType = parseBlockFuncType(builder);
if (failed(funcType))
return failure();
auto inputTypes = funcType->getInputs();
auto inputOps = popOperands(inputTypes);
if (failed(inputOps))
return failure();
Block *curBlock = builder.getBlock();
Region *curRegion = curBlock->getParent();
auto resTypes = funcType->getResults();
llvm::SmallVector<Location> locations{};
locations.resize(resTypes.size(), *currentOpLoc);
auto *successor =
builder.createBlock(curRegion, curRegion->end(), resTypes, locations);
builder.setInsertionPointToEnd(curBlock);
auto blockOp =
builder.create<OpToCreate>(*currentOpLoc, *inputOps, successor);
auto *blockBody = blockOp.createBlock();
if (failed(parseBlockContent(builder, blockBody, resTypes, *opLoc, blockOp)))
return failure();
builder.setInsertionPointToStart(successor);
return {ValueRange{successor->getArguments()}};
}
template <>
inline parsed_inst_t
ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::block>(
OpBuilder &builder) {
return parseBlockLikeOp<BlockOp>(builder);
}
template <>
inline parsed_inst_t
ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::loop>(
OpBuilder &builder) {
return parseBlockLikeOp<LoopOp>(builder);
}
template <>
inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
WasmBinaryEncoding::OpCode::ifOpCode>(OpBuilder &builder) {
auto opLoc = currentOpLoc;
auto funcType = parseBlockFuncType(builder);
if (failed(funcType))
return failure();
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<Location> locations{};
locations.resize(resTypes.size(), *currentOpLoc);
auto *successor =
builder.createBlock(curRegion, curRegion->end(), resTypes, locations);
builder.setInsertionPointToEnd(curBlock);
auto ifOp = builder.create<IfOp>(*currentOpLoc, conditionValue->front(),
*inputOps, successor);
auto *ifEntryBlock = ifOp.createIfBlock();
constexpr auto ifElseFilter =
ByteSequence<WasmBinaryEncoding::endByte,
WasmBinaryEncoding::OpCode::elseOpCode>{};
auto parseIfRes = parseBlockContent(builder, ifEntryBlock, resTypes, *opLoc,
ifOp, ifElseFilter);
if (failed(parseIfRes))
return failure();
if (*parseIfRes == WasmBinaryEncoding::OpCode::elseOpCode) {
LDBG() << " else block is present.";
Block *elseEntryBlock = ifOp.createElseBlock();
auto parseElseRes =
parseBlockContent(builder, elseEntryBlock, resTypes, *opLoc, ifOp);
if (failed(parseElseRes))
return failure();
}
builder.setInsertionPointToStart(successor);
return {ValueRange{successor->getArguments()}};
}
template <>
inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
WasmBinaryEncoding::OpCode::branchIf>(OpBuilder &builder) {
auto level = parser.parseLiteral<uint32_t>();
if (failed(level))
return failure();
Block *curBlock = builder.getBlock();
Region *curRegion = curBlock->getParent();
auto sip = builder.saveInsertionPoint();
Block *elseBlock = builder.createBlock(curRegion, curRegion->end());
auto condition = popOperands(builder.getI32Type());
if (failed(condition))
return failure();
builder.restoreInsertionPoint(sip);
auto targetOp =
LabelBranchingOpInterface::getTargetOpFromBlock(curBlock, *level);
if (failed(targetOp))
return failure();
auto inputTypes = targetOp->getLabelTarget()->getArgumentTypes();
auto branchArgs = popOperands(inputTypes);
if (failed(branchArgs))
return failure();
builder.create<BranchIfOp>(*currentOpLoc, condition->front(),
builder.getUI32IntegerAttr(*level), *branchArgs,
elseBlock);
builder.setInsertionPointToStart(elseBlock);
return {*branchArgs};
}
template <>
inline parsed_inst_t
ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::call>(
OpBuilder &builder) {
auto loc = *currentOpLoc;
auto funcIdx = parser.parseLiteral<uint32_t>();
if (failed(funcIdx))
return failure();
if (*funcIdx >= symbols.funcSymbols.size())
return emitError(loc, "Invalid function index: ") << *funcIdx;
auto callee = symbols.funcSymbols[*funcIdx];
llvm::ArrayRef<Type> inTypes = callee.functionType.getInputs();
llvm::ArrayRef<Type> resTypes = callee.functionType.getResults();
parsed_inst_t inOperands = popOperands(inTypes);
if (failed(inOperands))
return failure();
auto callOp =
builder.create<FuncCallOp>(loc, resTypes, callee.symbol, *inOperands);
return {callOp.getResults()};
}
template <>
inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
WasmBinaryEncoding::OpCode::localGet>(OpBuilder &builder) {
@@ -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 <typename opType, typename inputType, typename outputType,
typename... extraArgsT>
inline parsed_inst_t ExpressionParser::buildConvertOp(OpBuilder &builder,
extraArgsT... extraArgs) {
static_assert(std::is_arithmetic_v<inputType>,
"InputType should be an arithmetic type");
static_assert(std::is_arithmetic_v<outputType>,
"OutputType should be an arithmetic type");
auto intype = buildLiteralType<inputType>(builder);
auto outType = buildLiteralType<outputType>(builder);
auto operand = popOperands(intype);
if (failed(operand))
return failure();
auto op = builder.create<opType>(*currentOpLoc, outType, operand->front(),
extraArgs...);
LDBG() << "Built operation: " << op;
return {{op.getResult()}};
}
template <>
inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
WasmBinaryEncoding::OpCode::demoteF64ToF32>(OpBuilder &builder) {
return buildConvertOp<DemoteOp, double, float>(builder);
}
template <>
inline parsed_inst_t
ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::wrap>(
OpBuilder &builder) {
return buildConvertOp<WrapOp, int64_t, int32_t>(builder);
}
#define BUILD_CONVERSION_OP(IN_T, OUT_T, SOURCE_OP, TARGET_OP) \
template <> \
inline parsed_inst_t ExpressionParser::parseSpecificInstruction< \
WasmBinaryEncoding::OpCode::SOURCE_OP>(OpBuilder & builder) { \
return buildConvertOp<TARGET_OP, IN_T, OUT_T>(builder); \
}
#define BUILD_CONVERT_OP_FOR(DEST_T, WIDTH) \
BUILD_CONVERSION_OP(uint32_t, DEST_T, convertUI32F##WIDTH, ConvertUOp) \
BUILD_CONVERSION_OP(int32_t, DEST_T, convertSI32F##WIDTH, ConvertSOp) \
BUILD_CONVERSION_OP(uint64_t, DEST_T, convertUI64F##WIDTH, ConvertUOp) \
BUILD_CONVERSION_OP(int64_t, DEST_T, convertSI64F##WIDTH, ConvertSOp)
BUILD_CONVERT_OP_FOR(float, 32)
BUILD_CONVERT_OP_FOR(double, 64)
#undef BUILD_CONVERT_OP_FOR
BUILD_CONVERSION_OP(int32_t, int64_t, extendS, ExtendSI32Op)
BUILD_CONVERSION_OP(int32_t, int64_t, extendU, ExtendUI32Op)
#undef BUILD_CONVERSION_OP
#define BUILD_SLICE_EXTEND_PARSER(IT_WIDTH, EXTRACT_WIDTH) \
template <> \
parsed_inst_t ExpressionParser::parseSpecificInstruction< \
WasmBinaryEncoding::OpCode::extendI##IT_WIDTH##EXTRACT_WIDTH##S>( \
OpBuilder & builder) { \
using inout_t = int##IT_WIDTH##_t; \
auto attr = builder.getUI32IntegerAttr(EXTRACT_WIDTH); \
return buildConvertOp<ExtendLowBitsSOp, inout_t, inout_t>(builder, attr); \
}
BUILD_SLICE_EXTEND_PARSER(32, 8)
BUILD_SLICE_EXTEND_PARSER(32, 16)
BUILD_SLICE_EXTEND_PARSER(64, 8)
BUILD_SLICE_EXTEND_PARSER(64, 16)
BUILD_SLICE_EXTEND_PARSER(64, 32)
#undef BUILD_SLICE_EXTEND_PARSER
template <>
inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
WasmBinaryEncoding::OpCode::promoteF32ToF64>(OpBuilder &builder) {
return buildConvertOp<PromoteOp, float, double>(builder);
}
#define BUILD_REINTERPRET_PARSER(WIDTH, FP_TYPE) \
template <> \
inline parsed_inst_t ExpressionParser::parseSpecificInstruction< \
WasmBinaryEncoding::OpCode::reinterpretF##WIDTH##AsI##WIDTH>(OpBuilder & \
builder) { \
return buildConvertOp<ReinterpretOp, FP_TYPE, int##WIDTH##_t>(builder); \
} \
\
template <> \
inline parsed_inst_t ExpressionParser::parseSpecificInstruction< \
WasmBinaryEncoding::OpCode::reinterpretI##WIDTH##AsF##WIDTH>(OpBuilder & \
builder) { \
return buildConvertOp<ReinterpretOp, int##WIDTH##_t, FP_TYPE>(builder); \
}
BUILD_REINTERPRET_PARSER(32, float)
BUILD_REINTERPRET_PARSER(64, double)
#undef BUILD_REINTERPRET_PARSER
class WasmBinaryParser {
private:
struct SectionRegistry {
@@ -1153,7 +1594,7 @@ private:
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 @@ public:
FileLineColLoc magicLoc = parser.getLocation();
FailureOr<StringRef> 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<WasmSectionType::EXPORT>(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);
}

View File

@@ -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

View File

@@ -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<local ref to i32>) -> 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<local ref to i32>) -> i32 {
wasmssa.func @func_0(%arg0 : !wasmssa<local ref to i32>) -> 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<local ref to i32>) -> i32 {
wasmssa.return %retVal : f32
}
// CHECK-LABEL: wasmssa.func nested @func_1(
// CHECK-LABEL: wasmssa.func @func_1(
// CHECK-SAME: %[[ARG0:.*]]: !wasmssa<local ref to i32>) -> i32 {
// CHECK: %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: %[[VAL_1:.*]] = wasmssa.local of type i32
@@ -38,7 +38,7 @@ wasmssa.func nested @func_0(%arg0 : !wasmssa<local ref to i32>) -> 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<local ref to i32>) -> i32 {
wasmssa.func @func_1(%arg0 : !wasmssa<local ref to i32>) -> i32 {
%cond = wasmssa.local_get %arg0 : ref to i32
%var = wasmssa.local of type i32
%zero = wasmssa.const 0

View File

@@ -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<tabletype !wasmssa.funcref [2:]>}
wasmssa.import_mem "mem" from "my_module" as @mem_0 {limits = !wasmssa<limit[2:]>, 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<tabletype !wasmssa.funcref [2:]>}
// CHECK: wasmssa.import_mem "mem" from "my_module" as @mem_0 {limits = !wasmssa<limit[2:]>, 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

View File

@@ -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<local ref to i32>) -> i32 {
wasmssa.func @func_2(%arg0: !wasmssa<local ref to i32>) -> 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<local ref to i32>) -> i32 {
// CHECK: %[[VAL_0:.*]] = wasmssa.const 3 : i32
// CHECK: wasmssa.return %[[VAL_0]] : i32

View File

@@ -1,7 +1,7 @@
// RUN: mlir-opt %s | FileCheck %s
// CHECK: wasmssa.memory @mem0 public !wasmssa<limit[0: 65536]>
wasmssa.memory @mem0 public !wasmssa<limit[0:65536]>
// CHECK: wasmssa.memory @mem1 nested !wasmssa<limit[512:]>
// CHECK: wasmssa.memory @mem1 !wasmssa<limit[512:]>
wasmssa.memory @mem1 !wasmssa<limit[512:]>
// CHECK: wasmssa.memory exported @mem2 !wasmssa<limit[0: 65536]>
wasmssa.memory exported @mem2 !wasmssa<limit[0:65536]>

View File

@@ -1,7 +1,7 @@
// RUN: mlir-opt %s | FileCheck %s
// CHECK: wasmssa.table @tab0 public !wasmssa<tabletype !wasmssa.externref [0: 65536]>
wasmssa.table @tab0 public !wasmssa<tabletype !wasmssa.externref [0:65536]>
// CHECK: wasmssa.table exported @tab0 !wasmssa<tabletype !wasmssa.externref [0: 65536]>
wasmssa.table exported @tab0 !wasmssa<tabletype !wasmssa.externref [0:65536]>
// CHECK: wasmssa.table @tab1 nested !wasmssa<tabletype !wasmssa.funcref [348:]>
// CHECK: wasmssa.table @tab1 !wasmssa<tabletype !wasmssa.funcref [348:]>
wasmssa.table @tab1 !wasmssa<tabletype !wasmssa.funcref [348:]>

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -1,6 +1,6 @@
// RUN: mlir-opt %s -split-input-file -verify-diagnostics
wasmssa.func nested @local_set_err(%arg0: !wasmssa<local ref to i32>) -> i64 {
wasmssa.func @local_set_err(%arg0: !wasmssa<local ref to i32>) -> 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<local ref to i32>) -> i64 {
// -----
wasmssa.func nested @local_tee_err(%arg0: !wasmssa<local ref to i32>) -> i32 {
wasmssa.func @local_tee_err(%arg0: !wasmssa<local ref to i32>) -> 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

View File

@@ -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

View File

@@ -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<local ref to i32>,
// CHECK-SAME: %[[ARG1:.*]]: !wasmssa<local ref to i32>) -> i32 {
// CHECK: %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: %[[VAL_1:.*]] = wasmssa.call @func_0(%[[VAL_0]]) : (i32) -> i32
// CHECK: %[[VAL_2:.*]] = wasmssa.local_get %[[ARG1]] : ref to i32
// CHECK: %[[VAL_3:.*]] = wasmssa.call @func_0(%[[VAL_2]]) : (i32) -> i32
// CHECK: %[[VAL_4:.*]] = wasmssa.add %[[VAL_1]] %[[VAL_3]] : i32
// CHECK: %[[VAL_5:.*]] = wasmssa.const 2 : i32
// CHECK: %[[VAL_6:.*]] = wasmssa.div_si %[[VAL_4]] %[[VAL_5]] : i32
// CHECK: wasmssa.return %[[VAL_6]] : i32
// CHECK: }
// CHECK: wasmssa.memory exported @memory !wasmssa<limit[2:]>
// CHECK-LABEL: wasmssa.global @global_0 i32 mutable : {
// CHECK: %[[VAL_0:.*]] = wasmssa.const 66560 : i32
// CHECK: wasmssa.return %[[VAL_0]] : i32

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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: }

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<local ref to i32>) {
// CHECK: wasmssa.block : {
// CHECK: wasmssa.block : {
// CHECK: wasmssa.block : {
// CHECK: wasmssa.block_return
// CHECK: }> ^bb1
// CHECK: ^bb1:
// CHECK: wasmssa.block_return
// CHECK: }> ^bb1
// CHECK: ^bb1:
// CHECK: wasmssa.block_return
// CHECK: }> ^bb1
// CHECK: ^bb1:
// CHECK: wasmssa.return
// CHECK-LABEL: wasmssa.func @func_1(
// CHECK-SAME: %[[ARG0:.*]]: !wasmssa<local ref to i32>) {
// CHECK: wasmssa.block : {
// CHECK: wasmssa.block_return
// CHECK: }> ^bb1
// CHECK: ^bb1:
// CHECK: wasmssa.block : {
// CHECK: wasmssa.block_return
// CHECK: }> ^bb2
// CHECK: ^bb2:
// CHECK: wasmssa.block : {
// CHECK: wasmssa.block_return
// CHECK: }> ^bb3
// CHECK: ^bb3:
// CHECK: wasmssa.return

View File

@@ -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: }

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<local ref to i32>) -> i32 {
// CHECK: %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: %[[VAL_1:.*]] = wasmssa.const 1 : i32
// CHECK: %[[VAL_2:.*]] = wasmssa.and %[[VAL_0]] %[[VAL_1]] : i32
// CHECK: wasmssa.if %[[VAL_2]] : {
// CHECK: %[[VAL_3:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: %[[VAL_4:.*]] = wasmssa.const 3 : i32
// CHECK: %[[VAL_5:.*]] = wasmssa.mul %[[VAL_3]] %[[VAL_4]] : i32
// CHECK: %[[VAL_6:.*]] = wasmssa.const 1 : i32
// CHECK: %[[VAL_7:.*]] = wasmssa.add %[[VAL_5]] %[[VAL_6]] : i32
// CHECK: wasmssa.block_return %[[VAL_7]] : i32
// CHECK: } "else "{
// CHECK: %[[VAL_8:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: %[[VAL_9:.*]] = wasmssa.const 1 : i32
// CHECK: %[[VAL_10:.*]] = wasmssa.shr_u %[[VAL_8]] by %[[VAL_9]] bits : i32
// CHECK: wasmssa.block_return %[[VAL_10]] : i32
// CHECK: }> ^bb1
// CHECK: ^bb1(%[[VAL_11:.*]]: i32):
// CHECK: wasmssa.return %[[VAL_11]] : i32
// CHECK-LABEL: wasmssa.func @func_1(
// CHECK-SAME: %[[ARG0:.*]]: !wasmssa<local ref to i32>) -> i32 {
// CHECK: %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: %[[VAL_1:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: %[[VAL_2:.*]] = wasmssa.const 1 : i32
// CHECK: %[[VAL_3:.*]] = wasmssa.and %[[VAL_1]] %[[VAL_2]] : i32
// CHECK: wasmssa.if %[[VAL_3]](%[[VAL_0]]) : i32 : {
// CHECK: ^bb0(%[[VAL_4:.*]]: i32):
// CHECK: %[[VAL_5:.*]] = wasmssa.const 1 : i32
// CHECK: %[[VAL_6:.*]] = wasmssa.add %[[VAL_4]] %[[VAL_5]] : i32
// CHECK: wasmssa.block_return %[[VAL_6]] : i32
// CHECK: } > ^bb1
// CHECK: ^bb1(%[[VAL_7:.*]]: i32):
// CHECK: wasmssa.return %[[VAL_7]] : i32
// CHECK-LABEL: wasmssa.func @func_2(
// CHECK-SAME: %[[ARG0:.*]]: !wasmssa<local ref to i32>) -> i32 {
// CHECK: %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: %[[VAL_1:.*]] = wasmssa.ctz %[[VAL_0]] : i32
// CHECK: wasmssa.if %[[VAL_1]] : {
// CHECK: %[[VAL_2:.*]] = wasmssa.const 2 : i32
// CHECK: %[[VAL_3:.*]] = wasmssa.local_get %[[ARG0]] : ref to i32
// CHECK: %[[VAL_4:.*]] = wasmssa.const 1 : i32
// CHECK: %[[VAL_5:.*]] = wasmssa.shr_u %[[VAL_3]] by %[[VAL_4]] bits : i32
// CHECK: %[[VAL_6:.*]] = wasmssa.ctz %[[VAL_5]] : i32
// CHECK: wasmssa.if %[[VAL_6]](%[[VAL_2]]) : i32 : {
// CHECK: ^bb0(%[[VAL_7:.*]]: i32):
// CHECK: %[[VAL_8:.*]] = wasmssa.const 2 : i32
// CHECK: %[[VAL_9:.*]] = wasmssa.add %[[VAL_7]] %[[VAL_8]] : i32
// CHECK: wasmssa.block_return %[[VAL_9]] : i32
// CHECK: } > ^bb1
// CHECK: ^bb1(%[[VAL_10:.*]]: i32):
// CHECK: wasmssa.block_return %[[VAL_10]] : i32
// CHECK: } "else "{
// CHECK: %[[VAL_11:.*]] = wasmssa.const 1 : i32
// CHECK: wasmssa.block_return %[[VAL_11]] : i32
// CHECK: }> ^bb1
// CHECK: ^bb1(%[[VAL_12:.*]]: i32):
// CHECK: wasmssa.return %[[VAL_12]] : i32

View File

@@ -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<tabletype !wasmssa.funcref [2:]>}
// CHECK: wasmssa.import_mem "mem" from "my_module" as @mem_0 {limits = !wasmssa<limit[2:]>, 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<tabletype !wasmssa.funcref [2:]>}
// CHECK: wasmssa.import_mem "mem" from "my_module" as @mem_0 {limits = !wasmssa<limit[2:]>}
// 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

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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
...

View File

@@ -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

View File

@@ -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<local ref to i32>) -> i32 {
// CHECK: %[[VAL_0:.*]] = wasmssa.const 3 : i32
// CHECK: wasmssa.local_set %[[ARG0]] : ref to i32 to %[[VAL_0]] : i32

View File

@@ -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: }

View File

@@ -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

View File

@@ -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

View File

@@ -4,4 +4,4 @@
(module (memory 0 0))
*/
// CHECK-LABEL: wasmssa.memory @mem_0 nested !wasmssa<limit[0: 0]>
// CHECK-LABEL: wasmssa.memory @mem_0 !wasmssa<limit[0: 0]>

View File

@@ -4,4 +4,4 @@
(module (memory 0 65536))
*/
// CHECK-LABEL: wasmssa.memory @mem_0 nested !wasmssa<limit[0: 65536]>
// CHECK-LABEL: wasmssa.memory @mem_0 !wasmssa<limit[0: 65536]>

View File

@@ -4,4 +4,4 @@
(module (memory 1))
*/
// CHECK-LABEL: wasmssa.memory @mem_0 nested !wasmssa<limit[1:]>
// CHECK-LABEL: wasmssa.memory @mem_0 !wasmssa<limit[1:]>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<local ref to i64>) -> i32 {
// CHECK: %[[VAL_0:.*]] = wasmssa.local_get %[[ARG0]] : ref to i64
// CHECK: %[[VAL_1:.*]] = wasmssa.wrap %[[VAL_0]] : i64 to i32
// CHECK: wasmssa.return %[[VAL_1]] : i32

View File

@@ -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