From a5e9fdadb0f15f3dcdca84c2f275b181d2965598 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 11 Jan 2024 00:09:12 +0100 Subject: [PATCH 01/52] chore: bump to alpha version Signed-off-by: Henry Gressmann --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- crates/cli/Cargo.toml | 2 +- crates/parser/Cargo.toml | 2 +- crates/tinywasm/Cargo.toml | 4 ++-- crates/tinywasm/tests/generated/mvp.csv | 3 ++- crates/tinywasm/tests/generated/progress-mvp.svg | 8 ++++---- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0bbe617..4baa78c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1233,7 +1233,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tinywasm" -version = "0.2.0" +version = "0.3.0-alpha.0" dependencies = [ "eyre", "log", @@ -1250,7 +1250,7 @@ dependencies = [ [[package]] name = "tinywasm-cli" -version = "0.2.0" +version = "0.3.0-alpha.0" dependencies = [ "argh", "color-eyre", @@ -1262,7 +1262,7 @@ dependencies = [ [[package]] name = "tinywasm-parser" -version = "0.2.0" +version = "0.3.0-alpha.0" dependencies = [ "log", "tinywasm-types", @@ -1271,7 +1271,7 @@ dependencies = [ [[package]] name = "tinywasm-types" -version = "0.2.0" +version = "0.3.0-alpha.0" dependencies = [ "log", "rkyv", diff --git a/Cargo.toml b/Cargo.toml index 90f4e32..0d5f97b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ default-members=["crates/cli"] resolver="2" [workspace.package] -version="0.2.0" +version="0.3.0-alpha.0" edition="2021" license="MIT OR Apache-2.0" authors=["Henry Gressmann "] diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 65a9e72..9cde64e 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -14,7 +14,7 @@ path="src/bin.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tinywasm={version="0.2.0-alpha.0", path="../tinywasm", features=["std", "parser"]} +tinywasm={version="0.3.0-alpha.0", path="../tinywasm", features=["std", "parser"]} argh="0.1" color-eyre={version="0.6", default-features=false} log="0.4" diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml index 9e6dc71..1592f85 100644 --- a/crates/parser/Cargo.toml +++ b/crates/parser/Cargo.toml @@ -11,7 +11,7 @@ repository.workspace=true # fork of wasmparser with no_std support, see https://github.com/bytecodealliance/wasmtime/issues/3495 wasmparser={version="0.100", package="wasmparser-nostd", default-features=false} log={version="0.4", optional=true} -tinywasm-types={version="0.2.0-alpha.0", path="../types"} +tinywasm-types={version="0.3.0-alpha.0", path="../types"} [features] default=["std", "logging"] diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml index 931bb45..7063f4c 100644 --- a/crates/tinywasm/Cargo.toml +++ b/crates/tinywasm/Cargo.toml @@ -14,8 +14,8 @@ path="src/lib.rs" [dependencies] log={version="0.4", optional=true} -tinywasm-parser={version="0.2.0-alpha.0", path="../parser", default-features=false, optional=true} -tinywasm-types={version="0.2.0-alpha.0", path="../types", default-features=false} +tinywasm-parser={version="0.3.0-alpha.0", path="../parser", default-features=false, optional=true} +tinywasm-types={version="0.3.0-alpha.0", path="../types", default-features=false} [dev-dependencies] wasm-testsuite={path="../wasm-testsuite"} diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index a238586..5613da9 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,5 @@ 0.0.4,9258,10909,[{"name":"address.wast","passed":0,"failed":54},{"name":"align.wast","passed":0,"failed":109},{"name":"binary-leb128.wast","passed":66,"failed":25},{"name":"binary.wast","passed":104,"failed":8},{"name":"block.wast","passed":0,"failed":171},{"name":"br.wast","passed":0,"failed":21},{"name":"br_if.wast","passed":0,"failed":30},{"name":"br_table.wast","passed":0,"failed":25},{"name":"call.wast","passed":0,"failed":22},{"name":"call_indirect.wast","passed":0,"failed":56},{"name":"comments.wast","passed":4,"failed":4},{"name":"const.wast","passed":702,"failed":76},{"name":"conversions.wast","passed":0,"failed":93},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":0,"failed":61},{"name":"elem.wast","passed":0,"failed":76},{"name":"endianness.wast","passed":0,"failed":1},{"name":"exports.wast","passed":21,"failed":73},{"name":"f32.wast","passed":1005,"failed":1509},{"name":"f32_bitwise.wast","passed":1,"failed":363},{"name":"f32_cmp.wast","passed":2401,"failed":6},{"name":"f64.wast","passed":1005,"failed":1509},{"name":"f64_bitwise.wast","passed":1,"failed":363},{"name":"f64_cmp.wast","passed":2401,"failed":6},{"name":"fac.wast","passed":0,"failed":2},{"name":"float_exprs.wast","passed":269,"failed":591},{"name":"float_literals.wast","passed":34,"failed":129},{"name":"float_memory.wast","passed":0,"failed":6},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":4,"failed":75},{"name":"func_ptrs.wast","passed":0,"failed":16},{"name":"global.wast","passed":4,"failed":49},{"name":"i32.wast","passed":0,"failed":96},{"name":"i64.wast","passed":0,"failed":42},{"name":"if.wast","passed":0,"failed":118},{"name":"imports.wast","passed":1,"failed":156},{"name":"inline-module.wast","passed":0,"failed":1},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":5,"failed":46},{"name":"labels.wast","passed":1,"failed":28},{"name":"left-to-right.wast","passed":0,"failed":1},{"name":"linking.wast","passed":1,"failed":66},{"name":"load.wast","passed":0,"failed":60},{"name":"local_get.wast","passed":2,"failed":34},{"name":"local_set.wast","passed":5,"failed":48},{"name":"local_tee.wast","passed":0,"failed":42},{"name":"loop.wast","passed":0,"failed":43},{"name":"memory.wast","passed":0,"failed":34},{"name":"memory_grow.wast","passed":0,"failed":19},{"name":"memory_redundancy.wast","passed":0,"failed":1},{"name":"memory_size.wast","passed":0,"failed":6},{"name":"memory_trap.wast","passed":0,"failed":172},{"name":"names.wast","passed":484,"failed":1},{"name":"nop.wast","passed":0,"failed":5},{"name":"return.wast","passed":0,"failed":21},{"name":"select.wast","passed":0,"failed":32},{"name":"skip-stack-guard-page.wast","passed":0,"failed":11},{"name":"stack.wast","passed":0,"failed":2},{"name":"start.wast","passed":0,"failed":10},{"name":"store.wast","passed":0,"failed":59},{"name":"switch.wast","passed":1,"failed":27},{"name":"token.wast","passed":16,"failed":42},{"name":"traps.wast","passed":3,"failed":33},{"name":"type.wast","passed":1,"failed":2},{"name":"unreachable.wast","passed":0,"failed":59},{"name":"unreached-invalid.wast","passed":0,"failed":118},{"name":"unwind.wast","passed":1,"failed":49},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":0,"failed":176}] 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.2.0-alpha.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index e1fd709..9148772 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.1.0 (17630) -v0.2.0-alpha.0 (19344) +v0.2.0 (19344) - - - + + + From 9c82f366fc1e0ae8088660abe51d3708d42132f8 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 15 Jan 2024 18:44:16 +0100 Subject: [PATCH 02/52] chore: change panics to UnimplementedFeature errors Signed-off-by: Henry Gressmann --- Cargo.lock | 89 ++++++------------- crates/parser/src/conversion.rs | 6 +- crates/tinywasm/src/func.rs | 2 +- crates/tinywasm/src/runtime/executor/mod.rs | 16 ++-- .../tinywasm/src/runtime/stack/call_stack.rs | 49 ++-------- crates/tinywasm/src/store.rs | 55 ++++++++++-- crates/types/src/lib.rs | 11 +++ 7 files changed, 109 insertions(+), 119 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4baa78c..acd3d65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -222,15 +222,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - [[package]] name = "color-eyre" version = "0.6.2" @@ -488,9 +479,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "freetype" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" +checksum = "efc8599a3078adf8edeb86c71e9f8fa7d88af5ca31e806a867756081f90f5d83" dependencies = [ "freetype-sys", "libc", @@ -498,11 +489,11 @@ dependencies = [ [[package]] name = "freetype-sys" -version = "0.13.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +checksum = "66ee28c39a43d89fbed8b4798fb4ba56722cfd2b5af81f9326c27614ba88ecd5" dependencies = [ - "cmake", + "cc", "libc", "pkg-config", ] @@ -609,15 +600,14 @@ dependencies = [ [[package]] name = "image" -version = "0.24.7" +version = "0.24.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23" dependencies = [ "bytemuck", "byteorder", "color_quant", "jpeg-decoder", - "num-rational", "num-traits", "png", ] @@ -653,15 +643,15 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jpeg-decoder" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -733,27 +723,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.17" @@ -863,9 +832,9 @@ dependencies = [ [[package]] name = "png" -version = "0.17.10" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1067,9 +1036,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ "bitflags 2.4.1", "errno", @@ -1189,9 +1158,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -1331,9 +1300,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1341,9 +1310,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", @@ -1356,9 +1325,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1366,9 +1335,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", @@ -1379,9 +1348,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "wasm-encoder" @@ -1422,9 +1391,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index b9e674e..7b36dcd 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -1,5 +1,5 @@ use alloc::{boxed::Box, format, string::ToString, vec::Vec}; -use log::info; +use log::debug; use tinywasm_types::{ BlockArgs, ConstInstruction, ElementItem, Export, ExternalKind, FuncType, Global, GlobalType, Import, ImportKind, Instruction, MemArg, MemoryArch, MemoryType, TableType, ValType, @@ -322,7 +322,7 @@ pub fn process_operators<'a>( let mut labels_ptrs = Vec::new(); // indexes into the instructions array for op in ops { - info!("op: {:?}", op); + debug!("op: {:?}", op); let op = op?; validator.op(offset, &op)?; @@ -359,7 +359,7 @@ pub fn process_operators<'a>( } End => { if let Some(label_pointer) = labels_ptrs.pop() { - info!("ending block: {:?}", instructions[label_pointer]); + debug!("ending block: {:?}", instructions[label_pointer]); let current_instr_ptr = instructions.len(); diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index b0b359d..7a6fd1c 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -68,7 +68,7 @@ impl FuncHandle { let result_m = func_ty.results.len(); // 1. Assert: m values are on the top of the stack (Ensured by validation) - debug_assert!(stack.values.len() >= result_m); + assert!(stack.values.len() >= result_m); // 2. Pop m values from the stack let res = stack.values.last_n(result_m)?; diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 541c0a7..fe27d5a 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -7,7 +7,6 @@ use crate::{ CallFrame, Error, LabelArgs, ModuleInstance, Result, Store, }; use alloc::vec::Vec; -use log::info; use tinywasm_types::Instruction; mod macros; @@ -104,7 +103,7 @@ fn exec_one( store: &mut Store, module: &ModuleInstance, ) -> Result { - info!("ptr: {} instr: {:?}", cf.instr_ptr, instr); + debug!("ptr: {} instr: {:?}", cf.instr_ptr, instr); use tinywasm_types::Instruction::*; match instr { @@ -217,7 +216,11 @@ fn exec_one( .collect::>>()?; if instr.len() != *len { - panic!("Expected {} BrLabel instructions, got {}", len, instr.len()); + panic!( + "Expected {} BrLabel instructions, got {}, this should have been validated by the parser", + len, + instr.len() + ); } let idx = stack.values.pop_t::()? as usize; @@ -241,7 +244,7 @@ fn exec_one( }, EndFunc => { - debug_assert!( + assert!( cf.labels.len() == 0, "endfunc: block frames not empty, this should have been validated by the parser" ); @@ -499,7 +502,10 @@ fn exec_one( i => { log::error!("unimplemented instruction: {:?}", i); - panic!("Unimplemented instruction: {:?}", i) + return Err(Error::UnsupportedFeature(alloc::format!( + "unimplemented instruction: {:?}", + i + ))); } }; diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index 239659c..c4397c2 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -38,28 +38,13 @@ impl CallStack { Ok(self.stack.pop().unwrap()) } - #[inline] - pub(crate) fn _top(&self) -> Result<&CallFrame> { - assert!(self.top <= self.stack.len()); - if self.top == 0 { - return Err(Error::CallStackEmpty); - } - Ok(&self.stack[self.top - 1]) - } - - #[inline] - pub(crate) fn _top_mut(&mut self) -> Result<&mut CallFrame> { - assert!(self.top <= self.stack.len()); - if self.top == 0 { - return Err(Error::CallStackEmpty); - } - Ok(&mut self.stack[self.top - 1]) - } - #[inline] pub(crate) fn push(&mut self, call_frame: CallFrame) { - assert!(self.top <= self.stack.len()); - assert!(self.stack.len() <= CALL_STACK_MAX_SIZE); + assert!(self.top <= self.stack.len(), "stack is too small"); + assert!( + self.stack.len() <= CALL_STACK_MAX_SIZE, + "call stack size exceeded, this should have been caught" + ); self.top += 1; self.stack.push(call_frame); @@ -68,7 +53,6 @@ impl CallStack { #[derive(Debug, Clone)] pub(crate) struct CallFrame { - // having real pointers here would be nice :( but we can't really do that in safe rust pub(crate) instr_ptr: usize, pub(crate) func_ptr: usize, @@ -115,19 +99,6 @@ impl CallFrame { } } - // self.instr_ptr = block_frame.instr_ptr; - // value_stack.trim(block_frame.stack_ptr); - - // // // Adjusting how to trim the blocks stack based on the block type - // // let trim_index = match block_frame.block { - // // // if we are breaking to a loop, we want to jump back to the start of the loop - // // BlockFrameInner::Loop => block_index as usize - 1, - // // // if we are breaking to any other block, we want to jump to the end of the block - // // // TODO: check if this is correct - // // BlockFrameInner::If | BlockFrameInner::Else | BlockFrameInner::Block => block_index as usize - 1, - // // }; - - // self.block_frames.trim(block_index as usize); Some(()) } @@ -155,19 +126,13 @@ impl CallFrame { #[inline] pub(crate) fn set_local(&mut self, local_index: usize, value: RawWasmValue) { - if local_index >= self.local_count { - panic!("Invalid local index"); - } - + assert!(local_index < self.local_count, "Invalid local index"); self.locals[local_index] = value; } #[inline] pub(crate) fn get_local(&self, local_index: usize) -> RawWasmValue { - if local_index >= self.local_count { - panic!("Invalid local index"); - } - + assert!(local_index < self.local_count, "Invalid local index"); self.locals[local_index] } } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 564232d..73eb503 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -202,6 +202,21 @@ impl Store { Ok(global_addrs) } + pub(crate) fn eval_i32_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { + use tinywasm_types::ConstInstruction::*; + let val = match const_instr { + I32Const(i) => *i, + GlobalGet(addr) => { + let addr = *addr as usize; + let global = self.data.globals[addr].clone(); + let val = global.borrow().value; + i32::from(val) + } + _ => return Err(Error::Other("expected i32".to_string())), + }; + Ok(val) + } + pub(crate) fn eval_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { use tinywasm_types::ConstInstruction::*; let val = match const_instr { @@ -227,27 +242,50 @@ impl Store { let elem_count = self.data.elems.len(); let mut elem_addrs = Vec::with_capacity(elem_count); for (i, elem) in elems.into_iter().enumerate() { - match elem.kind { + let items = match elem.kind { // doesn't need to be initialized, can be initialized lazily using the `table.init` instruction - ElementKind::Passive => {} + ElementKind::Passive => None, + // TODO: ElementKind::Passive => Some(elem.items.iter().map(|item| item.addr()).collect()), // this one is active, so we need to initialize it (essentially a `table.init` instruction) - ElementKind::Active { .. } => { + ElementKind::Active { offset, table } => { + let init = elem + .items + .iter() + .map(|item| { + item.addr().ok_or_else(|| { + Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item)) + }) + }) + .collect::>>()?; + // a. Let n be the length of the vector elem[i].init + let n = elem.items.len(); + // b. Execute the instruction sequence einstrs + let table_idx = self.eval_i32_const(&offset)? as usize; + // c. Execute the instruction i32.const 0 + let elem_idx = 0; + // d. Execute the instruction i32.const n + let elem_count = n; + // e. Execute the instruction table.init tableidx i + // self.data.tables[table_idx].elements[elem_idx..elem_count].copy_from_slice(&init); + // f. Execute the instruction elm.drop i + None } // this one is not available to the runtime but needs to be initialized to declare references ElementKind::Declared => { // a. Execute the instruction elm.drop i + None } - } + }; - self.data.elems.push(ElemInstance::new(elem.kind, idx)); + self.data.elems.push(ElemInstance::new(elem.kind, idx, items)); elem_addrs.push((i + elem_count) as Addr); } @@ -377,7 +415,7 @@ pub(crate) struct MemoryInstance { impl MemoryInstance { pub(crate) fn new(kind: MemoryType, owner: ModuleInstanceAddr) -> Self { - debug_assert!(kind.page_count_initial <= kind.page_count_max.unwrap_or(MAX_PAGES as u64)); + assert!(kind.page_count_initial <= kind.page_count_max.unwrap_or(MAX_PAGES as u64)); log::debug!("initializing memory with {} pages", kind.page_count_initial); Self { @@ -480,12 +518,13 @@ impl GlobalInstance { #[derive(Debug)] pub(crate) struct ElemInstance { kind: ElementKind, + items: Option>, // none is the element was dropped owner: ModuleInstanceAddr, // index into store.module_instances } impl ElemInstance { - pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr) -> Self { - Self { kind, owner } + pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option>) -> Self { + Self { kind, owner, items } } } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index d3bf81a..4ea7b55 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -434,3 +434,14 @@ pub enum ElementItem { Func(FuncAddr), Expr(ConstInstruction), } + +impl ElementItem { + pub fn addr(&self) -> Option { + match self { + Self::Func(addr) => Some(*addr), + Self::Expr(ConstInstruction::RefFunc(addr)) => Some(*addr), + Self::Expr(ConstInstruction::RefNull(_ty)) => Some(0), + _ => None, + } + } +} From 1a97fa744e9f3536b437e484270de327c3b278fc Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 15 Jan 2024 23:28:40 +0100 Subject: [PATCH 03/52] feat: element instantiation Signed-off-by: Henry Gressmann --- crates/parser/src/conversion.rs | 12 ++++- crates/tinywasm/src/error.rs | 10 ++++ crates/tinywasm/src/instance.rs | 4 +- crates/tinywasm/src/runtime/value.rs | 1 + crates/tinywasm/src/store.rs | 67 +++++++++++++++---------- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/testsuite/util.rs | 2 +- crates/types/src/instructions.rs | 11 +++- crates/types/src/lib.rs | 8 +-- 9 files changed, 82 insertions(+), 35 deletions(-) diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index 7b36dcd..b1427c0 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -307,7 +307,7 @@ pub fn process_const_operator(op: wasmparser::Operator) -> Result Ok(ConstInstruction::F64Const(f64::from_bits(value.bits()))), // TODO: check if this is correct wasmparser::Operator::GlobalGet { global_index } => Ok(ConstInstruction::GlobalGet(global_index)), op => Err(crate::ParseError::UnsupportedOperator(format!( - "Unsupported instruction: {:?}", + "Unsupported const instruction: {:?}", op ))), } @@ -587,6 +587,16 @@ pub fn process_operators<'a>( I64TruncSatF32U => Instruction::I64TruncSatF32U, I64TruncSatF64S => Instruction::I64TruncSatF64S, I64TruncSatF64U => Instruction::I64TruncSatF64U, + TableGet { table } => Instruction::TableGet(table), + TableSet { table } => Instruction::TableSet(table), + TableInit { table, elem_index } => Instruction::TableInit(table, elem_index), + TableCopy { src_table, dst_table } => Instruction::TableCopy { + from: src_table, + to: dst_table, + }, + TableGrow { table } => Instruction::TableGrow(table), + TableSize { table } => Instruction::TableSize(table), + TableFill { table } => Instruction::TableFill(table), op => { log::error!("Unsupported instruction: {:?}", op); return Err(crate::ParseError::UnsupportedOperator(format!( diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index a7dac81..c58a257 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -22,6 +22,16 @@ pub enum Trap { max: usize, }, + /// An out-of-bounds table access occurred + TableOutOfBounds { + /// The offset of the access + offset: usize, + /// The size of the access + len: usize, + /// The maximum size of the memory + max: usize, + }, + /// A division by zero occurred DivisionByZero, diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index ad5e937..0e8e7e1 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -1,6 +1,6 @@ use alloc::{boxed::Box, string::ToString, sync::Arc, vec::Vec}; use tinywasm_types::{ - DataAddr, ElmAddr, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr, ModuleInstanceAddr, TableAddr, + DataAddr, ElemAddr, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr, ModuleInstanceAddr, TableAddr, }; use crate::{ @@ -27,7 +27,7 @@ pub(crate) struct ModuleInstanceInner { pub(crate) table_addrs: Vec, pub(crate) mem_addrs: Vec, pub(crate) global_addrs: Vec, - pub(crate) elem_addrs: Vec, + pub(crate) elem_addrs: Vec, pub(crate) data_addrs: Vec, pub(crate) func_start: Option, diff --git a/crates/tinywasm/src/runtime/value.rs b/crates/tinywasm/src/runtime/value.rs index b25f634..7db9891 100644 --- a/crates/tinywasm/src/runtime/value.rs +++ b/crates/tinywasm/src/runtime/value.rs @@ -42,6 +42,7 @@ impl From for RawWasmValue { WasmValue::F32(i) => Self(i.to_bits() as u64), WasmValue::F64(i) => Self(i.to_bits()), WasmValue::RefNull(_) => Self(0), + WasmValue::RefExtern(v) => Self(v as u64), } } } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 73eb503..499f32a 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -242,47 +242,40 @@ impl Store { let elem_count = self.data.elems.len(); let mut elem_addrs = Vec::with_capacity(elem_count); for (i, elem) in elems.into_iter().enumerate() { + let init = elem + .items + .iter() + .map(|item| { + item.addr().ok_or_else(|| { + Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item)) + }) + }) + .collect::>>()?; + let items = match elem.kind { // doesn't need to be initialized, can be initialized lazily using the `table.init` instruction - ElementKind::Passive => None, - // TODO: ElementKind::Passive => Some(elem.items.iter().map(|item| item.addr()).collect()), + ElementKind::Passive => Some(init), + + // this one is not available to the runtime but needs to be initialized to declare references + ElementKind::Declared => { + // a. Execute the instruction elm.drop i + None + } // this one is active, so we need to initialize it (essentially a `table.init` instruction) ElementKind::Active { offset, table } => { - let init = elem - .items - .iter() - .map(|item| { - item.addr().ok_or_else(|| { - Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item)) - }) - }) - .collect::>>()?; + let offset = self.eval_i32_const(&offset)?; // a. Let n be the length of the vector elem[i].init - let n = elem.items.len(); - // b. Execute the instruction sequence einstrs - let table_idx = self.eval_i32_const(&offset)? as usize; - // c. Execute the instruction i32.const 0 - let elem_idx = 0; - // d. Execute the instruction i32.const n - let elem_count = n; - // e. Execute the instruction table.init tableidx i - // self.data.tables[table_idx].elements[elem_idx..elem_count].copy_from_slice(&init); + self.data.tables[table as usize].init(offset, &init)?; // f. Execute the instruction elm.drop i None } - - // this one is not available to the runtime but needs to be initialized to declare references - ElementKind::Declared => { - // a. Execute the instruction elm.drop i - None - } }; self.data.elems.push(ElemInstance::new(elem.kind, idx, items)); @@ -396,6 +389,28 @@ impl TableInstance { owner, } } + + pub(crate) fn init(&mut self, offset: i32, init: &[Addr]) -> Result<()> { + let offset = offset as usize; + let end = offset.checked_add(init.len()).ok_or_else(|| { + Error::Trap(crate::Trap::TableOutOfBounds { + offset, + len: init.len(), + max: self.elements.len(), + }) + })?; + + if end > self.elements.len() || end < offset { + return Err(Error::Trap(crate::Trap::TableOutOfBounds { + offset, + len: init.len(), + max: self.elements.len(), + })); + } + + self.elements[offset..end].copy_from_slice(init); + Ok(()) + } } pub(crate) const PAGE_SIZE: usize = 65536; diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 5613da9..bb15caf 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -3,4 +3,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19346,882,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":60,"failed":39},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":104,"failed":6},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":78,"failed":105},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":28,"failed":104},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/testsuite/util.rs b/crates/tinywasm/tests/testsuite/util.rs index 9ba7934..99b94d4 100644 --- a/crates/tinywasm/tests/testsuite/util.rs +++ b/crates/tinywasm/tests/testsuite/util.rs @@ -73,7 +73,7 @@ pub fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result WasmValue::F64(f64::from_bits(f.bits)), I32(i) => WasmValue::I32(i), I64(i) => WasmValue::I64(i), - // RefExtern(v) => WasmValue::RefExtern(v), + RefExtern(v) => WasmValue::RefExtern(v), RefNull(t) => WasmValue::RefNull(match t { wast::core::HeapType::Func => tinywasm_types::ValType::FuncRef, wast::core::HeapType::Extern => tinywasm_types::ValType::ExternRef, diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs index 01c5b6e..c90f3df 100644 --- a/crates/types/src/instructions.rs +++ b/crates/types/src/instructions.rs @@ -1,4 +1,4 @@ -use crate::MemAddr; +use crate::{ElemAddr, MemAddr}; use super::{FuncAddr, GlobalAddr, LabelAddr, LocalAddr, TableAddr, TypeAddr, ValType}; @@ -257,4 +257,13 @@ pub enum Instruction { I64TruncSatF32U, I64TruncSatF64S, I64TruncSatF64U, + + // Table Instructions + TableInit(TableAddr, ElemAddr), + TableGet(TableAddr), + TableSet(TableAddr), + TableCopy { from: TableAddr, to: TableAddr }, + TableGrow(TableAddr), + TableSize(TableAddr), + TableFill(TableAddr), } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 4ea7b55..2e4fe4f 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -88,8 +88,8 @@ pub enum WasmValue { F64(f64), // Vec types // V128(i128), - // RefExtern(ExternAddr), // RefHost(FuncAddr), + RefExtern(ExternAddr), RefNull(ValType), } @@ -102,7 +102,7 @@ impl WasmValue { Self::F64(i) => ConstInstruction::F64Const(*i), Self::RefNull(ty) => ConstInstruction::RefNull(*ty), // Self::RefExtern(addr) => ConstInstruction::RefExtern(*addr), - // _ => unimplemented!("const_instr for {:?}", self), + _ => unimplemented!("no const_instr for {:?}", self), } } @@ -224,6 +224,7 @@ impl Debug for WasmValue { WasmValue::F32(i) => write!(f, "f32({})", i), WasmValue::F64(i) => write!(f, "f64({})", i), WasmValue::RefNull(ty) => write!(f, "ref.null({:?})", ty), + WasmValue::RefExtern(addr) => write!(f, "ref.extern({})", addr), // WasmValue::V128(i) => write!(f, "v128({})", i), } } @@ -238,6 +239,7 @@ impl WasmValue { Self::F32(_) => ValType::F32, Self::F64(_) => ValType::F64, Self::RefNull(ty) => *ty, + Self::RefExtern(_) => ValType::ExternRef, // Self::V128(_) => ValType::V128, } } @@ -293,7 +295,7 @@ pub type FuncAddr = Addr; pub type TableAddr = Addr; pub type MemAddr = Addr; pub type GlobalAddr = Addr; -pub type ElmAddr = Addr; +pub type ElemAddr = Addr; pub type DataAddr = Addr; pub type ExternAddr = Addr; // additional internal addresses From d64ed2b7ec2d025914197a467d5529acb8cc5b4a Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 16 Jan 2024 17:25:42 +0100 Subject: [PATCH 04/52] chore: improve imports Signed-off-by: Henry Gressmann --- crates/tinywasm/src/imports.rs | 49 ++++++++++++++++--- crates/tinywasm/src/runtime/value.rs | 3 +- crates/tinywasm/src/store.rs | 26 +++++++--- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 31 +++++------- crates/tinywasm/tests/testsuite/run.rs | 10 +++- crates/types/src/lib.rs | 43 +++++++++++++++- 7 files changed, 126 insertions(+), 38 deletions(-) diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 1b3a9cf..2a68535 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -3,29 +3,66 @@ use alloc::{ collections::BTreeMap, string::{String, ToString}, }; -use tinywasm_types::{Global, GlobalType, ModuleInstanceAddr, WasmValue}; +use tinywasm_types::{GlobalType, MemoryType, ModuleInstanceAddr, TableType, WasmValue}; #[derive(Debug)] #[non_exhaustive] /// An external value pub enum Extern { /// A global value - Global(Global), - // Func(HostFunc), - // Table(Table), + Global(ExternGlobal), + + /// A table + Table(ExternTable), + + /// A memory + Memory(ExternMemory), + + /// A function + Func, +} + +/// A global value +#[derive(Debug)] +pub struct ExternGlobal { + pub(crate) ty: GlobalType, + pub(crate) val: WasmValue, +} + +/// A table +#[derive(Debug)] +pub struct ExternTable { + pub(crate) ty: TableType, + pub(crate) val: WasmValue, +} + +/// A memory +#[derive(Debug)] +pub struct ExternMemory { + pub(crate) ty: MemoryType, } impl Extern { /// Create a new global import pub fn global(val: WasmValue, mutable: bool) -> Self { - Self::Global(Global { + Self::Global(ExternGlobal { ty: GlobalType { ty: val.val_type(), mutable, }, - init: val.const_instr(), + val, }) } + + /// Create a new table import + pub fn table(ty: TableType, val: WasmValue) -> Self { + Self::Table(ExternTable { ty, val }) + } + + /// Create a new memory import + pub fn memory(ty: MemoryType) -> Self { + Self::Memory(ExternMemory { ty }) + } } #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)] diff --git a/crates/tinywasm/src/runtime/value.rs b/crates/tinywasm/src/runtime/value.rs index 7db9891..096d576 100644 --- a/crates/tinywasm/src/runtime/value.rs +++ b/crates/tinywasm/src/runtime/value.rs @@ -41,8 +41,9 @@ impl From for RawWasmValue { WasmValue::I64(i) => Self(i as u64), WasmValue::F32(i) => Self(i.to_bits() as u64), WasmValue::F64(i) => Self(i.to_bits()), - WasmValue::RefNull(_) => Self(0), + WasmValue::RefNull(v) => v.default_value().into(), WasmValue::RefExtern(v) => Self(v as u64), + WasmValue::RefFunc(v) => Self(v as u64), } } } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 499f32a..d64c853 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -173,8 +173,6 @@ impl Store { }; match global { Extern::Global(global) => Ok(global), - - #[allow(unreachable_patterns)] // this is non-exhaustive _ => Err(Error::Other(format!( "expected global import for {}::{}", import.module, import.name @@ -185,12 +183,20 @@ impl Store { let global_count = self.data.globals.len(); let mut global_addrs = Vec::with_capacity(global_count); - log::debug!("globals: {:?}", globals); - let globals = globals.into_iter(); - let iterator = imported_globals.into_iter().chain(globals.as_ref()); - for (i, global) in iterator.enumerate() { + // first add the imported globals + for (i, global) in imported_globals.iter().enumerate() { + self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new( + global.ty, + global.val.into(), + idx, + )))); + global_addrs.push((i + global_count) as Addr); + } + + // then add the module globals + for (i, global) in globals.iter().enumerate() { self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new( global.ty, self.eval_const(&global.init)?, @@ -230,7 +236,7 @@ impl Store { let val = global.borrow().value; val } - RefNull(_) => RawWasmValue::default(), + RefNull(v) => v.default_value().into(), RefFunc(idx) => RawWasmValue::from(*idx as i64), }; Ok(val) @@ -271,7 +277,11 @@ impl Store { // c. Execute the instruction i32.const 0 // d. Execute the instruction i32.const n // e. Execute the instruction table.init tableidx i - self.data.tables[table as usize].init(offset, &init)?; + if let Some(table) = self.data.tables.get_mut(table as usize) { + table.init(offset, &init)?; + } else { + log::error!("table {} not found", table); + } // f. Execute the instruction elm.drop i None diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index bb15caf..62506b4 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -3,4 +3,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19346,882,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":60,"failed":39},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":104,"failed":6},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":78,"failed":105},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":28,"failed":104},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19352,876,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":72,"failed":27},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":30,"failed":102},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 9148772..bc63592 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -36,29 +36,22 @@ TinyWasm Version - + v0.0.3 (9258) - - -v0.0.4 (9258) - - - + + v0.0.5 (11135) - - -v0.1.0 (17630) - - - + + v0.2.0 (19344) - - - - - - + + + + + + + diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 8a1ddf4..14d4c17 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -8,7 +8,7 @@ use super::TestSuite; use eyre::{eyre, Result}; use log::{debug, error, info}; use tinywasm::{Extern, Imports, ModuleInstance}; -use tinywasm_types::{ModuleInstanceAddr, WasmValue}; +use tinywasm_types::{MemoryType, ModuleInstanceAddr, TableType, ValType, WasmValue}; use wast::{lexer::Lexer, parser::ParseBuffer, Wast}; impl TestSuite { @@ -25,7 +25,15 @@ impl TestSuite { fn imports(registered_modules: Vec<(String, ModuleInstanceAddr)>) -> Result { let mut imports = Imports::new(); + let memory = Extern::memory(MemoryType::new_32(1, Some(2))); + let table = Extern::table( + TableType::new(ValType::FuncRef, 10, Some(20)), + WasmValue::default_for(ValType::FuncRef), + ); + imports + .define("spectest", "memory", memory)? + .define("spectest", "table", table)? .define("spectest", "global_i32", Extern::global(WasmValue::I32(666), false))? .define("spectest", "global_i64", Extern::global(WasmValue::I64(666), false))? .define("spectest", "global_f32", Extern::global(WasmValue::F32(666.0), false))? diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 2e4fe4f..00ccdfa 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -91,6 +91,7 @@ pub enum WasmValue { // RefHost(FuncAddr), RefExtern(ExternAddr), RefNull(ValType), + RefFunc(FuncAddr), } impl WasmValue { @@ -114,8 +115,8 @@ impl WasmValue { ValType::F32 => Self::F32(0.0), ValType::F64 => Self::F64(0.0), ValType::V128 => unimplemented!("V128 is not yet supported"), - ValType::FuncRef => unimplemented!("FuncRef is not yet supported"), - ValType::ExternRef => unimplemented!("ExternRef is not yet supported"), + ValType::FuncRef => Self::RefFunc(0), + ValType::ExternRef => Self::RefExtern(0), } } @@ -225,6 +226,7 @@ impl Debug for WasmValue { WasmValue::F64(i) => write!(f, "f64({})", i), WasmValue::RefNull(ty) => write!(f, "ref.null({:?})", ty), WasmValue::RefExtern(addr) => write!(f, "ref.extern({})", addr), + WasmValue::RefFunc(addr) => write!(f, "ref.func({})", addr), // WasmValue::V128(i) => write!(f, "v128({})", i), } } @@ -240,6 +242,7 @@ impl WasmValue { Self::F64(_) => ValType::F64, Self::RefNull(ty) => *ty, Self::RefExtern(_) => ValType::ExternRef, + Self::RefFunc(_) => ValType::FuncRef, // Self::V128(_) => ValType::V128, } } @@ -372,6 +375,24 @@ pub struct TableType { pub size_max: Option, } +impl TableType { + pub fn empty() -> Self { + Self { + element_type: ValType::FuncRef, + size_initial: 0, + size_max: None, + } + } + + pub fn new(element_type: ValType, size_initial: u32, size_max: Option) -> Self { + Self { + element_type, + size_initial, + size_max, + } + } +} + #[derive(Debug, Clone)] /// Represents a memory's type. @@ -382,6 +403,24 @@ pub struct MemoryType { pub page_count_max: Option, } +impl MemoryType { + pub fn new_32(page_count_initial: u64, page_count_max: Option) -> Self { + Self { + arch: MemoryArch::I32, + page_count_initial, + page_count_max, + } + } + + // pub fn new_64(page_count_initial: u64, page_count_max: Option) -> Self { + // Self { + // arch: MemoryArch::I64, + // page_count_initial, + // page_count_max, + // } + // } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum MemoryArch { I32, From 22f7425bf0b72d04b764fa636d79f7aeb7b12e3e Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 16 Jan 2024 18:06:49 +0100 Subject: [PATCH 05/52] feat: initial linking Signed-off-by: Henry Gressmann --- crates/tinywasm/src/error.rs | 36 ++++++++++ crates/tinywasm/src/export.rs | 16 ++--- crates/tinywasm/src/imports.rs | 93 +++++++++++++++++++++++-- crates/tinywasm/src/instance.rs | 11 ++- crates/tinywasm/src/store.rs | 4 ++ crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/testsuite/run.rs | 4 +- crates/types/src/lib.rs | 11 +++ 8 files changed, 156 insertions(+), 21 deletions(-) diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index c58a257..1d5dbc0 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -79,6 +79,30 @@ pub enum Error { /// The store is not the one that the module instance was instantiated in InvalidStore, + + /// Missing import + MissingImport { + /// The module name + module: String, + /// The import name + name: String, + }, + + /// Could not resolve an import + CouldNotResolveImport { + /// The module name + module: String, + /// The import name + name: String, + }, + + /// Invalid import type + InvalidImportType { + /// The module name + module: String, + /// The import name + name: String, + }, } impl Display for Error { @@ -100,6 +124,18 @@ impl Display for Error { Self::StackUnderflow => write!(f, "stack underflow"), Self::CallStackEmpty => write!(f, "call stack empty"), Self::InvalidStore => write!(f, "invalid store"), + + Self::MissingImport { module, name } => { + write!(f, "missing import: {}.{}", module, name) + } + + Self::CouldNotResolveImport { module, name } => { + write!(f, "could not resolve import: {}.{}", module, name) + } + + Self::InvalidImportType { module, name } => { + write!(f, "invalid import type: {}.{}", module, name) + } } } } diff --git a/crates/tinywasm/src/export.rs b/crates/tinywasm/src/export.rs index c6ae6d3..52adc6f 100644 --- a/crates/tinywasm/src/export.rs +++ b/crates/tinywasm/src/export.rs @@ -1,18 +1,18 @@ -use alloc::{boxed::Box, format}; +use alloc::boxed::Box; use tinywasm_types::{Export, ExternalKind}; -use crate::{Error, Result}; - #[derive(Debug)] /// Exports of a module instance +// TODO: Maybe use a BTreeMap instead? pub struct ExportInstance(pub(crate) Box<[Export]>); impl ExportInstance { /// Get an export by name - pub fn get(&self, name: &str, ty: ExternalKind) -> Result<&Export> { - self.0 - .iter() - .find(|e| e.name == name.into() && e.kind == ty) - .ok_or(Error::Other(format!("export {} not found", name))) + pub fn get(&self, name: &str, ty: ExternalKind) -> Option<&Export> { + self.0.iter().find(|e| e.name == name.into() && e.kind == ty) + } + + pub(crate) fn get_untyped(&self, name: &str) -> Option<&Export> { + self.0.iter().find(|e| e.name == name.into()) } } diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 2a68535..3a8f393 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -3,7 +3,7 @@ use alloc::{ collections::BTreeMap, string::{String, ToString}, }; -use tinywasm_types::{GlobalType, MemoryType, ModuleInstanceAddr, TableType, WasmValue}; +use tinywasm_types::{ExternVal, ExternalKind, GlobalType, MemoryType, ModuleInstanceAddr, TableType, WasmValue}; #[derive(Debug)] #[non_exhaustive] @@ -63,6 +63,15 @@ impl Extern { pub fn memory(ty: MemoryType) -> Self { Self::Memory(ExternMemory { ty }) } + + pub(crate) fn kind(&self) -> ExternalKind { + match self { + Self::Global(_) => ExternalKind::Global, + Self::Table(_) => ExternalKind::Table, + Self::Memory(_) => ExternalKind::Memory, + Self::Func => ExternalKind::Func, + } + } } #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)] @@ -80,12 +89,16 @@ pub struct Imports { } pub(crate) struct LinkedImports { - pub(crate) values: BTreeMap, + // externs that were defined and need to be instantiated + pub(crate) externs: BTreeMap, + + // externs that were linked to other modules and already exist in the store + pub(crate) linked_externs: BTreeMap, } impl LinkedImports { pub(crate) fn get(&self, module: &str, name: &str) -> Option<&Extern> { - self.values.get(&ExternName { + self.externs.get(&ExternName { module: module.to_string(), name: name.to_string(), }) @@ -103,7 +116,7 @@ impl Imports { /// Link a module /// - /// This will automatically link all imported values + /// This will automatically link all imported values on instantiation pub fn link_module(&mut self, name: &str, addr: ModuleInstanceAddr) -> Result<&mut Self> { self.modules.insert(name.to_string(), addr); Ok(self) @@ -121,9 +134,75 @@ impl Imports { Ok(self) } - pub(crate) fn link(self, _store: &mut crate::Store, _module: &crate::Module) -> Result { + pub(crate) fn link(self, store: &mut crate::Store, module: &crate::Module) -> Result { + let mut links = BTreeMap::new(); + + for import in module.data.imports.iter() { + if let Some(i) = self.values.get(&ExternName { + module: import.module.to_string(), + name: import.name.to_string(), + }) { + if i.kind() != (&import.kind).into() { + return Err(crate::Error::InvalidImportType { + module: import.module.to_string(), + name: import.name.to_string(), + }); + } + + continue; + } + + let module_addr = + self.modules + .get(&import.module.to_string()) + .ok_or_else(|| crate::Error::MissingImport { + module: import.module.to_string(), + name: import.name.to_string(), + })?; + + let module = + store + .get_module_instance(*module_addr) + .ok_or_else(|| crate::Error::CouldNotResolveImport { + module: import.module.to_string(), + name: import.name.to_string(), + })?; + + let export = module.exports().get_untyped(&import.name.to_string()).ok_or_else(|| { + crate::Error::CouldNotResolveImport { + module: import.module.to_string(), + name: import.name.to_string(), + } + })?; + + // validate import + if export.kind != (&import.kind).into() { + return Err(crate::Error::InvalidImportType { + module: import.module.to_string(), + name: import.name.to_string(), + }); + } + + let val = match export.kind { + ExternalKind::Func => ExternVal::Func(export.index.clone()), + ExternalKind::Global => ExternVal::Global(export.index.clone()), + ExternalKind::Table => ExternVal::Table(export.index.clone()), + ExternalKind::Memory => ExternVal::Mem(export.index.clone()), + }; + + links.insert( + ExternName { + module: import.module.to_string(), + name: import.name.to_string(), + }, + val, + ); + } + // TODO: link to other modules (currently only direct imports are supported) - let values = self.values; - Ok(LinkedImports { values }) + Ok(LinkedImports { + externs: self.values, + linked_externs: links, + }) } } diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 0e8e7e1..81a0944 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -1,4 +1,4 @@ -use alloc::{boxed::Box, string::ToString, sync::Arc, vec::Vec}; +use alloc::{boxed::Box, format, string::ToString, sync::Arc, vec::Vec}; use tinywasm_types::{ DataAddr, ElemAddr, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr, ModuleInstanceAddr, TableAddr, }; @@ -142,7 +142,12 @@ impl ModuleInstance { return Err(Error::InvalidStore); } - let export = self.0.exports.get(name, ExternalKind::Func)?; + let export = self + .0 + .exports + .get(name, ExternalKind::Func) + .ok_or_else(|| Error::Other(format!("Export not found: {}", name)))?; + let func_addr = self.0.func_addrs[export.index as usize]; let func = store.get_func(func_addr as usize)?; let ty = self.0.types[func.ty_addr() as usize].clone(); @@ -184,7 +189,7 @@ impl ModuleInstance { Some(func_index) => func_index, None => { // alternatively, check for a _start function in the exports - let Ok(start) = self.0.exports.get("_start", ExternalKind::Func) else { + let Some(start) = self.0.exports.get("_start", ExternalKind::Func) else { return Ok(None); }; diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index d64c853..7e18768 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -49,6 +49,10 @@ impl Store { Self::default() } + pub(crate) fn get_module_instance(&self, addr: ModuleInstanceAddr) -> Option<&ModuleInstance> { + self.module_instances.get(addr as usize) + } + /// Create a new store with the given runtime pub(crate) fn runtime(&self) -> runtime::DefaultRuntime { match self.runtime { diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 62506b4..c3df599 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -3,4 +3,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19352,876,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":72,"failed":27},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":30,"failed":102},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19302,926,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":69,"failed":30},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":9,"failed":27},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":52,"failed":131},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":17,"failed":115},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 14d4c17..7a13c3a 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -101,7 +101,7 @@ impl TestSuite { // TODO: modules are not properly isolated from each other - tests fail because of this otherwise store = tinywasm::Store::default(); debug!("got wat module"); - let result = catch_unwind(AssertUnwindSafe(|| { + let result = catch_unwind_silent(|| { let m = parse_module_bytes(&module.encode().expect("failed to encode module")) .expect("failed to parse module bytes"); tinywasm::Module::from(m) @@ -111,7 +111,7 @@ impl TestSuite { e }) .expect("failed to instantiate module") - })) + }) .map_err(|e| eyre!("failed to parse wat module: {:?}", try_downcast_panic(e))); match &result { diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 00ccdfa..63f0133 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -442,6 +442,17 @@ pub enum ImportKind { Global(GlobalType), } +impl From<&ImportKind> for ExternalKind { + fn from(kind: &ImportKind) -> Self { + match kind { + ImportKind::Func(_) => Self::Func, + ImportKind::Table(_) => Self::Table, + ImportKind::Mem(_) => Self::Memory, + ImportKind::Global(_) => Self::Global, + } + } +} + #[derive(Debug, Clone)] pub struct Data { pub data: Box<[u8]>, From 8d0514b7c10dea2b10cd32895ac0da33c2312481 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 16 Jan 2024 18:50:05 +0100 Subject: [PATCH 06/52] chore: trap on negative memory adresses Signed-off-by: Henry Gressmann --- crates/tinywasm/src/instance.rs | 2 +- .../tinywasm/src/runtime/executor/macros.rs | 22 +++++++--- crates/tinywasm/src/store.rs | 41 +++++++++++++------ crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 8 ++-- 5 files changed, 51 insertions(+), 24 deletions(-) diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 81a0944..3225411 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -66,7 +66,7 @@ impl ModuleInstance { let elem_addrs = store.add_elems(module.data.elements.into(), idx)?; // TODO: active data segments need to be initialized - let data_addrs = store.add_datas(module.data.data.into(), idx); + let data_addrs = store.add_datas(module.data.data.into(), idx)?; let instance = ModuleInstanceInner { store_id: store.id(), diff --git a/crates/tinywasm/src/runtime/executor/macros.rs b/crates/tinywasm/src/runtime/executor/macros.rs index 8a92ac2..6d37c9a 100644 --- a/crates/tinywasm/src/runtime/executor/macros.rs +++ b/crates/tinywasm/src/runtime/executor/macros.rs @@ -17,13 +17,25 @@ macro_rules! mem_load { let addr = $stack.values.pop()?.raw_value(); + let addr = $arg.offset.checked_add(addr).ok_or_else(|| { + Error::Trap(crate::Trap::MemoryOutOfBounds { + offset: $arg.offset as usize, + len: core::mem::size_of::<$load_type>(), + max: mem.borrow().max_pages(), + }) + })?; + + let addr: usize = addr.try_into().ok().ok_or_else(|| { + Error::Trap(crate::Trap::MemoryOutOfBounds { + offset: $arg.offset as usize, + len: core::mem::size_of::<$load_type>(), + max: mem.borrow().max_pages(), + }) + })?; + let val: [u8; core::mem::size_of::<$load_type>()] = { let mem = mem.borrow_mut(); - let val = mem.load( - ($arg.offset + addr) as usize, - $arg.align as usize, - core::mem::size_of::<$load_type>(), - )?; + let val = mem.load(addr, $arg.align as usize, core::mem::size_of::<$load_type>())?; val.try_into().expect("slice with incorrect length") }; diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 7e18768..936238e 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -300,28 +300,39 @@ impl Store { } /// Add data to the store, returning their addresses in the store - pub(crate) fn add_datas(&mut self, datas: Vec, idx: ModuleInstanceAddr) -> Vec { + pub(crate) fn add_datas(&mut self, datas: Vec, idx: ModuleInstanceAddr) -> Result> { let data_count = self.data.datas.len(); let mut data_addrs = Vec::with_capacity(data_count); for (i, data) in datas.into_iter().enumerate() { - self.data.datas.push(DataInstance::new(data.data.to_vec(), idx)); - data_addrs.push((i + data_count) as Addr); - use tinywasm_types::DataKind::*; match data.kind { - Active { .. } => { + Active { mem: mem_addr, offset } => { // a. Assert: memidx == 0 - // b. Let n be the length of the vector - // c. Execute the instruction sequence - // d. Execute the instruction - // e. Execute the instruction - // f. Execute the instruction - // g. Execute the instruction + if mem_addr != 0 { + return Err(Error::UnsupportedFeature( + "data segments for non-zero memories".to_string(), + )); + } + + let offset = self.eval_i32_const(&offset)?; + + let mem = + self.data.mems.get_mut(mem_addr as usize).ok_or_else(|| { + Error::Other(format!("memory {} not found for data segment {}", mem_addr, i)) + })?; + + mem.borrow_mut().store(offset as usize, 0, &data.data)?; + + // drop the date + continue; } Passive => {} } + + self.data.datas.push(DataInstance::new(data.data.to_vec(), idx)); + data_addrs.push((i + data_count) as Addr); } - data_addrs + Ok(data_addrs) } /// Get the function at the actual index in the store @@ -477,12 +488,16 @@ impl MemoryInstance { Ok(()) } + pub(crate) fn max_pages(&self) -> usize { + self.kind.page_count_max.unwrap_or(MAX_PAGES as u64) as usize + } + pub(crate) fn load(&self, addr: usize, _align: usize, len: usize) -> Result<&[u8]> { let end = addr.checked_add(len).ok_or_else(|| { Error::Trap(crate::Trap::MemoryOutOfBounds { offset: addr, len, - max: self.data.len(), + max: self.max_pages(), }) })?; diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index c3df599..f47b0d3 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -3,4 +3,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19302,926,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":69,"failed":30},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":9,"failed":27},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":52,"failed":131},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":17,"failed":115},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19412,816,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":69,"failed":30},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":9,"failed":27},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index bc63592..700770d 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -48,10 +48,10 @@ v0.0.5 (11135) v0.2.0 (19344) - - - - + + + + From 77a8bf002476f501882317dff121714c959d9c8b Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 16 Jan 2024 18:53:26 +0100 Subject: [PATCH 07/52] docs: remove old testsuite results Signed-off-by: Henry Gressmann --- crates/tinywasm/tests/generated/mvp.csv | 1 - .../tinywasm/tests/generated/progress-mvp.svg | 33 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index f47b0d3..8cf24bd 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -1,4 +1,3 @@ -0.0.3,9258,7567,[{"name":"address.wast","passed":0,"failed":54},{"name":"align.wast","passed":0,"failed":109},{"name":"binary-leb128.wast","passed":66,"failed":25},{"name":"binary.wast","passed":104,"failed":8},{"name":"block.wast","passed":0,"failed":171},{"name":"br.wast","passed":0,"failed":21},{"name":"br_if.wast","passed":0,"failed":30},{"name":"br_table.wast","passed":0,"failed":25},{"name":"call.wast","passed":0,"failed":22},{"name":"call_indirect.wast","passed":0,"failed":56},{"name":"comments.wast","passed":4,"failed":4},{"name":"const.wast","passed":702,"failed":76},{"name":"conversions.wast","passed":0,"failed":93},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":0,"failed":61},{"name":"elem.wast","passed":0,"failed":76},{"name":"endianness.wast","passed":0,"failed":1},{"name":"exports.wast","passed":21,"failed":73},{"name":"f32.wast","passed":1005,"failed":1509},{"name":"f32_bitwise.wast","passed":1,"failed":363},{"name":"f32_cmp.wast","passed":2401,"failed":6},{"name":"f64.wast","passed":1005,"failed":1509},{"name":"f64_bitwise.wast","passed":1,"failed":363},{"name":"f64_cmp.wast","passed":2401,"failed":6},{"name":"fac.wast","passed":0,"failed":2},{"name":"float_exprs.wast","passed":269,"failed":591},{"name":"float_literals.wast","passed":34,"failed":129},{"name":"float_memory.wast","passed":0,"failed":6},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":4,"failed":75},{"name":"func_ptrs.wast","passed":0,"failed":16},{"name":"global.wast","passed":4,"failed":49},{"name":"i32.wast","passed":0,"failed":96},{"name":"i64.wast","passed":0,"failed":42},{"name":"if.wast","passed":0,"failed":118},{"name":"imports.wast","passed":1,"failed":156},{"name":"inline-module.wast","passed":0,"failed":1},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":5,"failed":46},{"name":"labels.wast","passed":1,"failed":28},{"name":"left-to-right.wast","passed":0,"failed":1},{"name":"linking.wast","passed":1,"failed":66},{"name":"load.wast","passed":0,"failed":60},{"name":"local_get.wast","passed":2,"failed":34},{"name":"local_set.wast","passed":5,"failed":48},{"name":"local_tee.wast","passed":0,"failed":42},{"name":"loop.wast","passed":0,"failed":43},{"name":"memory.wast","passed":0,"failed":34},{"name":"memory_grow.wast","passed":0,"failed":19},{"name":"memory_redundancy.wast","passed":0,"failed":1},{"name":"memory_size.wast","passed":0,"failed":6},{"name":"memory_trap.wast","passed":0,"failed":172},{"name":"names.wast","passed":484,"failed":1},{"name":"nop.wast","passed":0,"failed":5},{"name":"return.wast","passed":0,"failed":21},{"name":"select.wast","passed":0,"failed":32},{"name":"skip-stack-guard-page.wast","passed":0,"failed":11},{"name":"stack.wast","passed":0,"failed":2},{"name":"start.wast","passed":0,"failed":10},{"name":"store.wast","passed":0,"failed":59},{"name":"switch.wast","passed":1,"failed":27},{"name":"token.wast","passed":16,"failed":42},{"name":"traps.wast","passed":3,"failed":33},{"name":"type.wast","passed":1,"failed":2},{"name":"unreachable.wast","passed":0,"failed":59},{"name":"unreached-invalid.wast","passed":0,"failed":118},{"name":"unwind.wast","passed":1,"failed":49},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":0,"failed":176}] 0.0.4,9258,10909,[{"name":"address.wast","passed":0,"failed":54},{"name":"align.wast","passed":0,"failed":109},{"name":"binary-leb128.wast","passed":66,"failed":25},{"name":"binary.wast","passed":104,"failed":8},{"name":"block.wast","passed":0,"failed":171},{"name":"br.wast","passed":0,"failed":21},{"name":"br_if.wast","passed":0,"failed":30},{"name":"br_table.wast","passed":0,"failed":25},{"name":"call.wast","passed":0,"failed":22},{"name":"call_indirect.wast","passed":0,"failed":56},{"name":"comments.wast","passed":4,"failed":4},{"name":"const.wast","passed":702,"failed":76},{"name":"conversions.wast","passed":0,"failed":93},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":0,"failed":61},{"name":"elem.wast","passed":0,"failed":76},{"name":"endianness.wast","passed":0,"failed":1},{"name":"exports.wast","passed":21,"failed":73},{"name":"f32.wast","passed":1005,"failed":1509},{"name":"f32_bitwise.wast","passed":1,"failed":363},{"name":"f32_cmp.wast","passed":2401,"failed":6},{"name":"f64.wast","passed":1005,"failed":1509},{"name":"f64_bitwise.wast","passed":1,"failed":363},{"name":"f64_cmp.wast","passed":2401,"failed":6},{"name":"fac.wast","passed":0,"failed":2},{"name":"float_exprs.wast","passed":269,"failed":591},{"name":"float_literals.wast","passed":34,"failed":129},{"name":"float_memory.wast","passed":0,"failed":6},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":4,"failed":75},{"name":"func_ptrs.wast","passed":0,"failed":16},{"name":"global.wast","passed":4,"failed":49},{"name":"i32.wast","passed":0,"failed":96},{"name":"i64.wast","passed":0,"failed":42},{"name":"if.wast","passed":0,"failed":118},{"name":"imports.wast","passed":1,"failed":156},{"name":"inline-module.wast","passed":0,"failed":1},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":5,"failed":46},{"name":"labels.wast","passed":1,"failed":28},{"name":"left-to-right.wast","passed":0,"failed":1},{"name":"linking.wast","passed":1,"failed":66},{"name":"load.wast","passed":0,"failed":60},{"name":"local_get.wast","passed":2,"failed":34},{"name":"local_set.wast","passed":5,"failed":48},{"name":"local_tee.wast","passed":0,"failed":42},{"name":"loop.wast","passed":0,"failed":43},{"name":"memory.wast","passed":0,"failed":34},{"name":"memory_grow.wast","passed":0,"failed":19},{"name":"memory_redundancy.wast","passed":0,"failed":1},{"name":"memory_size.wast","passed":0,"failed":6},{"name":"memory_trap.wast","passed":0,"failed":172},{"name":"names.wast","passed":484,"failed":1},{"name":"nop.wast","passed":0,"failed":5},{"name":"return.wast","passed":0,"failed":21},{"name":"select.wast","passed":0,"failed":32},{"name":"skip-stack-guard-page.wast","passed":0,"failed":11},{"name":"stack.wast","passed":0,"failed":2},{"name":"start.wast","passed":0,"failed":10},{"name":"store.wast","passed":0,"failed":59},{"name":"switch.wast","passed":1,"failed":27},{"name":"token.wast","passed":16,"failed":42},{"name":"traps.wast","passed":3,"failed":33},{"name":"type.wast","passed":1,"failed":2},{"name":"unreachable.wast","passed":0,"failed":59},{"name":"unreached-invalid.wast","passed":0,"failed":118},{"name":"unwind.wast","passed":1,"failed":49},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":0,"failed":176}] 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 700770d..48f78da 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -36,22 +36,29 @@ TinyWasm Version - -v0.0.3 (9258) + +v0.0.4 (9258) - - + + v0.0.5 (11135) - - + + +v0.1.0 (17630) + + + v0.2.0 (19344) - - - - - - - + + +v0.3.0-alpha.0 (19412) + + + + + + + From 888fe588480516ebe3d4e0e3e8a6af0c07f66076 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Wed, 17 Jan 2024 22:57:15 +0100 Subject: [PATCH 08/52] chore: decrease max call stack size and fix corresponding tests Signed-off-by: Henry Gressmann --- .cargo/config.toml | 1 + crates/tinywasm/src/error.rs | 29 +++++++++++++-- crates/tinywasm/src/func.rs | 2 +- crates/tinywasm/src/runtime/executor/mod.rs | 8 ++--- .../tinywasm/src/runtime/stack/call_stack.rs | 18 +++++----- crates/tinywasm/src/store.rs | 5 +-- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/test-wast.rs | 2 +- crates/tinywasm/tests/testsuite/run.rs | 36 ++++++++++++++++++- 9 files changed, 82 insertions(+), 21 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 3e15584..7ccfd76 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -4,4 +4,5 @@ dev="run -- -l debug run" test-mvp="test --package tinywasm --test test-mvp --release -- --enable " test-wast="test --package tinywasm --test test-wast -- --enable " +test-wast-release="test --package tinywasm --test test-wast --release -- --enable " generate-charts="test --package tinywasm --test generate-charts -- --enable " diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index 1d5dbc0..9121e72 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -40,6 +40,24 @@ pub enum Trap { /// Integer Overflow IntegerOverflow, + + /// Call stack overflow + CallStackOverflow, +} + +impl Trap { + /// Get the message of the trap + pub fn message(&self) -> &'static str { + match self { + Self::Unreachable => "unreachable", + Self::MemoryOutOfBounds { .. } => "memory out of bounds", + Self::TableOutOfBounds { .. } => "table out of bounds", + Self::DivisionByZero => "division by zero", + Self::InvalidConversionToInt => "invalid conversion to int", + Self::IntegerOverflow => "integer overflow", + Self::CallStackOverflow => "call stack exhausted", + } + } } #[derive(Debug)] @@ -105,6 +123,12 @@ pub enum Error { }, } +impl From for Error { + fn from(value: Trap) -> Self { + Self::Trap(value) + } +} + impl Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { @@ -114,15 +138,14 @@ impl Display for Error { #[cfg(feature = "std")] Self::Io(err) => write!(f, "I/O error: {}", err), - Self::Trap(trap) => write!(f, "trap: {:?}", trap), - + Self::Trap(trap) => write!(f, "trap: {}", trap.message()), + Self::CallStackEmpty => write!(f, "call stack empty"), Self::InvalidLabelType => write!(f, "invalid label type"), Self::Other(message) => write!(f, "unknown error: {}", message), Self::UnsupportedFeature(feature) => write!(f, "unsupported feature: {}", feature), Self::FuncDidNotReturn => write!(f, "function did not return"), Self::LabelStackUnderflow => write!(f, "label stack underflow"), Self::StackUnderflow => write!(f, "stack underflow"), - Self::CallStackEmpty => write!(f, "call stack empty"), Self::InvalidStore => write!(f, "invalid store"), Self::MissingImport { module, name } => { diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 7a6fd1c..e422d25 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -58,7 +58,7 @@ impl FuncHandle { // 7. Push the frame f to the call stack // & 8. Push the values to the stack (Not needed since the call frame owns the values) - stack.call_stack.push(call_frame); + stack.call_stack.push(call_frame)?; // 9. Invoke the function instance let runtime = store.runtime(); diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index fe27d5a..00ab55e 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -53,7 +53,7 @@ impl DefaultRuntime { cf.instr_ptr += 1; // push the call frame back onto the stack so that it can be resumed // if the trap can be handled - stack.call_stack.push(cf); + stack.call_stack.push(cf)?; return Err(Error::Trap(trap)); } } @@ -138,8 +138,8 @@ fn exec_one( // push the call frame cf.instr_ptr += 1; // skip the call instruction - stack.call_stack.push(cf.clone()); - stack.call_stack.push(call_frame); + stack.call_stack.push(cf.clone())?; + stack.call_stack.push(call_frame)?; // call the function return Ok(ExecResult::Call); @@ -148,7 +148,7 @@ fn exec_one( If(args, else_offset, end_offset) => { if stack.values.pop_t::()? == 0 { if let Some(else_offset) = else_offset { - log::info!("entering else at {}", cf.instr_ptr + *else_offset); + log::debug!("entering else at {}", cf.instr_ptr + *else_offset); cf.enter_label( LabelFrame { instr_ptr: cf.instr_ptr + *else_offset, diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index c4397c2..28ea621 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -1,12 +1,12 @@ -use crate::{runtime::RawWasmValue, BlockType, Error, LabelFrame, Result}; +use crate::{runtime::RawWasmValue, BlockType, Error, LabelFrame, Result, Trap}; use alloc::{boxed::Box, vec::Vec}; use tinywasm_types::{ValType, WasmValue}; use super::blocks::Labels; // minimum call stack size -const CALL_STACK_SIZE: usize = 1024; -const CALL_STACK_MAX_SIZE: usize = 1024 * 1024; +const CALL_STACK_SIZE: usize = 128; +const CALL_STACK_MAX_SIZE: usize = 1024; #[derive(Debug)] pub(crate) struct CallStack { @@ -39,15 +39,17 @@ impl CallStack { } #[inline] - pub(crate) fn push(&mut self, call_frame: CallFrame) { + pub(crate) fn push(&mut self, call_frame: CallFrame) -> Result<()> { assert!(self.top <= self.stack.len(), "stack is too small"); - assert!( - self.stack.len() <= CALL_STACK_MAX_SIZE, - "call stack size exceeded, this should have been caught" - ); + + log::info!("stack size: {}", self.stack.len()); + if self.stack.len() >= CALL_STACK_MAX_SIZE { + return Err(Trap::CallStackOverflow.into()); + } self.top += 1; self.stack.push(call_frame); + Ok(()) } } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 936238e..5b644ba 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -426,11 +426,12 @@ impl TableInstance { })?; if end > self.elements.len() || end < offset { - return Err(Error::Trap(crate::Trap::TableOutOfBounds { + return Err(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len(), - })); + } + .into()); } self.elements[offset..end].copy_from_slice(init); diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 8cf24bd..89fecbd 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19412,816,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":69,"failed":30},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":9,"failed":27},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19425,803,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":75,"failed":16},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":69,"failed":30},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":9,"failed":27},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/test-wast.rs b/crates/tinywasm/tests/test-wast.rs index 42f7091..56bb39e 100644 --- a/crates/tinywasm/tests/test-wast.rs +++ b/crates/tinywasm/tests/test-wast.rs @@ -34,7 +34,7 @@ fn main() -> Result<()> { } fn test_wast(wast_file: &str) -> Result<()> { - TestSuite::set_log_level(log::LevelFilter::Debug); + TestSuite::set_log_level(log::LevelFilter::Info); let args = std::env::args().collect::>(); println!("args: {:?}", args); diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 7a13c3a..6f86edb 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -7,7 +7,7 @@ use std::{ use super::TestSuite; use eyre::{eyre, Result}; use log::{debug, error, info}; -use tinywasm::{Extern, Imports, ModuleInstance}; +use tinywasm::{Extern, Imports, ModuleInstance, Trap}; use tinywasm_types::{MemoryType, ModuleInstanceAddr, TableType, ValType, WasmValue}; use wast::{lexer::Lexer, parser::ParseBuffer, Wast}; @@ -169,6 +169,40 @@ impl TestSuite { ); } + AssertExhaustion { call, message, span } => { + let module = last_module.as_ref(); + let name = call.name; + + let args = call + .args + .into_iter() + .map(wastarg2tinywasmvalue) + .collect::>>() + .expect("failed to convert args"); + + let res = catch_unwind_silent(|| exec_fn_instance(module, &mut store, name, &args).map(|_| ())); + + let Ok(Err(tinywasm::Error::Trap(trap))) = res else { + test_group.add_result( + &format!("AssertExhaustion({})", i), + span.linecol_in(wast), + Err(eyre!("expected trap")), + ); + continue; + }; + + if trap.message() != message { + test_group.add_result( + &format!("AssertExhaustion({})", i), + span.linecol_in(wast), + Err(eyre!("expected trap: {}", message)), + ); + continue; + } + + test_group.add_result(&format!("AssertExhaustion({})", i), span.linecol_in(wast), Ok(())); + } + AssertTrap { exec, message: _, span } => { let res: Result, _> = catch_unwind_silent(|| { let (module, name, args) = match exec { From b0aa952383e08cae68644099c3bec6b7143a5206 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 18 Jan 2024 00:29:00 +0100 Subject: [PATCH 09/52] feat: table operations, various spec related fixes Signed-off-by: Henry Gressmann --- crates/tinywasm/src/instance.rs | 6 +- crates/tinywasm/src/runtime/executor/mod.rs | 57 +++++++++++++++++-- crates/tinywasm/src/runtime/value.rs | 7 ++- crates/tinywasm/src/store.rs | 48 +++++++++++++++- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 8 +-- 6 files changed, 111 insertions(+), 17 deletions(-) diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 3225411..7fd30aa 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -122,10 +122,14 @@ impl ModuleInstance { } // resolve a table address to the global store address - pub(crate) fn _resolve_table_addr(&self, addr: TableAddr) -> TableAddr { + pub(crate) fn resolve_table_addr(&self, addr: TableAddr) -> TableAddr { self.0.table_addrs[addr as usize] } + pub(crate) fn resolve_elem_addr(&self, addr: ElemAddr) -> ElemAddr { + self.0.elem_addrs[addr as usize] + } + // resolve a memory address to the global store address pub(crate) fn resolve_mem_addr(&self, addr: MemAddr) -> MemAddr { self.0.mem_addrs[addr as usize] diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 00ab55e..ee0d7d3 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -6,7 +6,7 @@ use crate::{ runtime::{BlockType, LabelFrame}, CallFrame, Error, LabelArgs, ModuleInstance, Result, Store, }; -use alloc::vec::Vec; +use alloc::{string::ToString, vec::Vec}; use tinywasm_types::Instruction; mod macros; @@ -16,10 +16,10 @@ use traits::*; impl DefaultRuntime { pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack, module: ModuleInstance) -> Result<()> { - log::info!("exports: {:?}", module.exports()); - log::info!("func_addrs: {:?}", module.func_addrs()); - log::info!("func_ty_addrs: {:?}", module.func_ty_addrs().len()); - log::info!("store funcs: {:?}", store.data.funcs.len()); + log::debug!("exports: {:?}", module.exports()); + log::debug!("func_addrs: {:?}", module.func_addrs()); + log::debug!("func_ty_addrs: {:?}", module.func_ty_addrs().len()); + log::debug!("store funcs: {:?}", store.data.funcs.len()); // The current call frame, gets updated inside of exec_one let mut cf = stack.call_stack.pop()?; @@ -124,6 +124,7 @@ fn exec_one( stack.values.push(val2); } } + Call(v) => { debug!("start call"); // prepare the call frame @@ -145,6 +146,29 @@ fn exec_one( return Ok(ExecResult::Call); } + CallIndirect(_type_addr, table_addr) => { + let table_idx = module.resolve_table_addr(*table_addr); + let table = store.get_table(table_idx as usize)?; + + let func_idx = stack.values.pop_t::()?; + let func_addr = table.borrow().get(func_idx as usize)?; + + // prepare the call frame + let func = store.get_func(func_addr as usize)?; + let func_ty = module.func_ty(func.ty_addr()); + + let params = stack.values.pop_n(func_ty.params.len())?; + let call_frame = CallFrame::new_raw(func_addr as usize, ¶ms, func.locals().to_vec()); + + // push the call frame + cf.instr_ptr += 1; // skip the call instruction + stack.call_stack.push(cf.clone())?; + stack.call_stack.push(call_frame)?; + + // call the function + return Ok(ExecResult::Call); + } + If(args, else_offset, end_offset) => { if stack.values.pop_t::()? == 0 { if let Some(else_offset) = else_offset { @@ -306,7 +330,7 @@ fn exec_one( MemoryGrow(addr, byte) => { if *byte != 0 { - unimplemented!("memory.grow with byte != 0"); + return Err(Error::UnsupportedFeature("memory.grow with byte != 0".to_string())); } let mem_idx = module.resolve_mem_addr(*addr); @@ -500,6 +524,27 @@ fn exec_one( I64TruncF32U => checked_conv_float!(f32, u64, i64, stack), I64TruncF64U => checked_conv_float!(f64, u64, i64, stack), + TableGet(table_index) => { + let table_idx = module.resolve_table_addr(*table_index); + let table = store.get_table(table_idx as usize)?; + let idx = stack.values.pop_t::()? as usize; + stack.values.push(table.borrow().get(idx)?.into()); + } + + TableSet(table_index) => { + let table_idx = module.resolve_table_addr(*table_index); + let table = store.get_table(table_idx as usize)?; + let idx = stack.values.pop_t::()? as usize; + let val = stack.values.pop_t::()?; + table.borrow_mut().set(idx, val)?; + } + + TableSize(table_index) => { + let table_idx = module.resolve_table_addr(*table_index); + let table = store.get_table(table_idx as usize)?; + stack.values.push(table.borrow().size().into()); + } + i => { log::error!("unimplemented instruction: {:?}", i); return Err(Error::UnsupportedFeature(alloc::format!( diff --git a/crates/tinywasm/src/runtime/value.rs b/crates/tinywasm/src/runtime/value.rs index 096d576..fec1214 100644 --- a/crates/tinywasm/src/runtime/value.rs +++ b/crates/tinywasm/src/runtime/value.rs @@ -27,8 +27,8 @@ impl RawWasmValue { ValType::I64 => WasmValue::I64(self.0 as i64), ValType::F32 => WasmValue::F32(f32::from_bits(self.0 as u32)), ValType::F64 => WasmValue::F64(f64::from_bits(self.0)), - ValType::ExternRef => todo!("externref"), - ValType::FuncRef => todo!("funcref"), + ValType::ExternRef => WasmValue::RefExtern(self.0 as u32), + ValType::FuncRef => WasmValue::RefFunc(self.0 as u32), ValType::V128 => todo!("v128"), } } @@ -73,5 +73,8 @@ impl_from_raw_wasm_value!(i64, |x| x as u64, |x| x as i64); impl_from_raw_wasm_value!(f32, |x| f32::to_bits(x) as u64, |x| f32::from_bits(x as u32)); impl_from_raw_wasm_value!(f64, f64::to_bits, f64::from_bits); +// convenience impls (not actually part of the spec) impl_from_raw_wasm_value!(i8, |x| x as u64, |x| x as i8); impl_from_raw_wasm_value!(i16, |x| x as u64, |x| x as i16); +impl_from_raw_wasm_value!(u32, |x| x as u64, |x| x as u32); +impl_from_raw_wasm_value!(u64, |x| x as u64, |x| x as u64); diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 5b644ba..b425554 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -89,7 +89,7 @@ impl Default for Store { // TODO: Arena allocate these? pub(crate) struct StoreData { pub(crate) funcs: Vec>, - pub(crate) tables: Vec, + pub(crate) tables: Vec>>, pub(crate) mems: Vec>>, pub(crate) globals: Vec>>, pub(crate) elems: Vec, @@ -129,7 +129,10 @@ impl Store { let table_count = self.data.tables.len(); let mut table_addrs = Vec::with_capacity(table_count); for (i, table) in tables.into_iter().enumerate() { - self.data.tables.push(TableInstance::new(table, idx)); + self.data + .tables + .push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); + table_addrs.push((i + table_count) as TableAddr); } table_addrs @@ -282,7 +285,7 @@ impl Store { // d. Execute the instruction i32.const n // e. Execute the instruction table.init tableidx i if let Some(table) = self.data.tables.get_mut(table as usize) { - table.init(offset, &init)?; + table.borrow_mut().init(offset, &init)?; } else { log::error!("table {} not found", table); } @@ -351,6 +354,21 @@ impl Store { .ok_or_else(|| Error::Other(format!("memory {} not found", addr))) } + /// Get the table at the actual index in the store + pub(crate) fn get_table(&self, addr: usize) -> Result<&Rc>> { + self.data + .tables + .get(addr) + .ok_or_else(|| Error::Other(format!("table {} not found", addr))) + } + + pub(crate) fn get_elem(&self, addr: usize) -> Result<&ElemInstance> { + self.data + .elems + .get(addr) + .ok_or_else(|| Error::Other(format!("element {} not found", addr))) + } + /// Get the global at the actual index in the store pub(crate) fn get_global_val(&self, addr: usize) -> Result { self.data @@ -415,6 +433,25 @@ impl TableInstance { } } + pub(crate) fn get(&self, addr: usize) -> Result { + self.elements + .get(addr) + .copied() + .ok_or_else(|| Error::Other(format!("table element {} not found", addr))) + } + + pub(crate) fn set(&mut self, addr: usize, value: Addr) -> Result<()> { + if addr >= self.elements.len() { + return Err(Error::Other(format!("table element {} not found", addr))); + } + self.elements[addr] = value; + Ok(()) + } + + pub(crate) fn size(&self) -> i32 { + self.elements.len() as i32 + } + pub(crate) fn init(&mut self, offset: i32, init: &[Addr]) -> Result<()> { let offset = offset as usize; let end = offset.checked_add(init.len()).ok_or_else(|| { @@ -527,6 +564,11 @@ impl MemoryInstance { return Err(Error::Other(format!("memory size out of bounds: {}", new_pages))); } let new_size = new_pages as usize * PAGE_SIZE; + + if self.max_pages() < new_pages as usize { + return Ok(current_pages); + } + if new_size > MAX_SIZE { return Err(Error::Other(format!("memory size out of bounds: {}", new_size))); } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 89fecbd..1cea924 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19425,803,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":75,"failed":16},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":69,"failed":30},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":9,"failed":27},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19567,661,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":75,"failed":16},{"name":"call_indirect.wast","passed":143,"failed":27},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":25,"failed":11},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":94,"failed":2},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 48f78da..bbfe15b 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (19412) +v0.3.0-alpha.0 (19567) + - - - + + From b497565836faa0caa12cdc044e1396156aa6c326 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 18 Jan 2024 00:43:18 +0100 Subject: [PATCH 10/52] feat: use the correct trap names, improve div trap Signed-off-by: Henry Gressmann --- crates/tinywasm/src/error.rs | 8 ++++---- crates/tinywasm/src/runtime/executor/macros.rs | 18 ++++++++++++------ crates/tinywasm/src/runtime/executor/mod.rs | 18 +++++++++--------- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/testsuite/run.rs | 15 ++++++++++++--- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index 9121e72..2d5a87f 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -50,10 +50,10 @@ impl Trap { pub fn message(&self) -> &'static str { match self { Self::Unreachable => "unreachable", - Self::MemoryOutOfBounds { .. } => "memory out of bounds", - Self::TableOutOfBounds { .. } => "table out of bounds", - Self::DivisionByZero => "division by zero", - Self::InvalidConversionToInt => "invalid conversion to int", + Self::MemoryOutOfBounds { .. } => "out of bounds memory access", + Self::TableOutOfBounds { .. } => "out of bounds table access", + Self::DivisionByZero => "integer divide by zero", + Self::InvalidConversionToInt => "invalid conversion to integer", Self::IntegerOverflow => "integer overflow", Self::CallStackOverflow => "call stack exhausted", } diff --git a/crates/tinywasm/src/runtime/executor/macros.rs b/crates/tinywasm/src/runtime/executor/macros.rs index 6d37c9a..48c50f4 100644 --- a/crates/tinywasm/src/runtime/executor/macros.rs +++ b/crates/tinywasm/src/runtime/executor/macros.rs @@ -201,13 +201,13 @@ macro_rules! arithmetic_single { } /// Apply an arithmetic operation to two values on the stack with error checking -macro_rules! checked_arithmetic { +macro_rules! checked_int_arithmetic { // Direct conversion with error checking (two types) - ($from:tt, $to:tt, $stack:ident, $trap:expr) => {{ - checked_arithmetic!($from, $to, $to, $stack, $trap) + ($from:tt, $to:tt, $stack:ident) => {{ + checked_int_arithmetic!($from, $to, $to, $stack) }}; - ($op:ident, $from:ty, $to:ty, $stack:ident, $trap:expr) => {{ + ($op:ident, $from:ty, $to:ty, $stack:ident) => {{ let [a, b] = $stack.values.pop_n_const::<2>()?; let a: $from = a.into(); let b: $from = b.into(); @@ -215,7 +215,13 @@ macro_rules! checked_arithmetic { let a_casted: $to = a as $to; let b_casted: $to = b as $to; - let result = a_casted.$op(b_casted).ok_or_else(|| Error::Trap($trap))?; + if b_casted == 0 { + return Err(Error::Trap(crate::Trap::DivisionByZero)); + } + + let result = a_casted + .$op(b_casted) + .ok_or_else(|| Error::Trap(crate::Trap::IntegerOverflow))?; // Cast back to original type if different $stack.values.push((result as $from).into()); @@ -224,8 +230,8 @@ macro_rules! checked_arithmetic { pub(super) use arithmetic; pub(super) use arithmetic_single; -pub(super) use checked_arithmetic; pub(super) use checked_conv_float; +pub(super) use checked_int_arithmetic; pub(super) use comp; pub(super) use comp_zero; pub(super) use conv; diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index ee0d7d3..4b0a328 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -433,15 +433,15 @@ fn exec_one( F64Mul => arithmetic!(*, f64, stack), // these can trap - I32DivS => checked_arithmetic!(checked_div, i32, stack, crate::Trap::DivisionByZero), - I64DivS => checked_arithmetic!(checked_div, i64, stack, crate::Trap::DivisionByZero), - I32DivU => checked_arithmetic!(checked_div, i32, u32, stack, crate::Trap::DivisionByZero), - I64DivU => checked_arithmetic!(checked_div, i64, u64, stack, crate::Trap::DivisionByZero), - - I32RemS => checked_arithmetic!(checked_wrapping_rem, i32, stack, crate::Trap::DivisionByZero), - I64RemS => checked_arithmetic!(checked_wrapping_rem, i64, stack, crate::Trap::DivisionByZero), - I32RemU => checked_arithmetic!(checked_wrapping_rem, i32, u32, stack, crate::Trap::DivisionByZero), - I64RemU => checked_arithmetic!(checked_wrapping_rem, i64, u64, stack, crate::Trap::DivisionByZero), + I32DivS => checked_int_arithmetic!(checked_div, i32, stack), + I64DivS => checked_int_arithmetic!(checked_div, i64, stack), + I32DivU => checked_int_arithmetic!(checked_div, i32, u32, stack), + I64DivU => checked_int_arithmetic!(checked_div, i64, u64, stack), + + I32RemS => checked_int_arithmetic!(checked_wrapping_rem, i32, stack), + I64RemS => checked_int_arithmetic!(checked_wrapping_rem, i64, stack), + I32RemU => checked_int_arithmetic!(checked_wrapping_rem, i32, u32, stack), + I64RemU => checked_int_arithmetic!(checked_wrapping_rem, i64, u64, stack), I32And => arithmetic!(bitand, i32, stack), I64And => arithmetic!(bitand, i64, stack), diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 1cea924..b1a0adc 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19567,661,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":75,"failed":16},{"name":"call_indirect.wast","passed":143,"failed":27},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":25,"failed":11},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":94,"failed":2},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19566,662,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":75,"failed":16},{"name":"call_indirect.wast","passed":142,"failed":28},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":25,"failed":11},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":94,"failed":2},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 6f86edb..8b31a88 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -195,7 +195,7 @@ impl TestSuite { test_group.add_result( &format!("AssertExhaustion({})", i), span.linecol_in(wast), - Err(eyre!("expected trap: {}", message)), + Err(eyre!("expected trap: {}, got: {}", message, trap.message())), ); continue; } @@ -203,7 +203,7 @@ impl TestSuite { test_group.add_result(&format!("AssertExhaustion({})", i), span.linecol_in(wast), Ok(())); } - AssertTrap { exec, message: _, span } => { + AssertTrap { exec, message, span } => { let res: Result, _> = catch_unwind_silent(|| { let (module, name, args) = match exec { wast::WastExecute::Wat(mut wat) => { @@ -236,7 +236,16 @@ impl TestSuite { span.linecol_in(wast), Err(eyre!("test panicked: {:?}", try_downcast_panic(err))), ), - Ok(Err(tinywasm::Error::Trap(_))) => { + Ok(Err(tinywasm::Error::Trap(trap))) => { + if trap.message() != message { + test_group.add_result( + &format!("AssertTrap({})", i), + span.linecol_in(wast), + Err(eyre!("expected trap: {}, got: {}", message, trap.message())), + ); + continue; + } + test_group.add_result(&format!("AssertTrap({})", i), span.linecol_in(wast), Ok(())) } Ok(Err(err)) => test_group.add_result( From 23e832392aa396d87ce8da2e4903bb238a73beff Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 18 Jan 2024 13:33:03 +0100 Subject: [PATCH 11/52] chore: improve indirect calls Signed-off-by: Henry Gressmann --- crates/tinywasm/src/error.rs | 24 +++++++++++++++++++ crates/tinywasm/src/runtime/executor/mod.rs | 14 +++++++++-- crates/tinywasm/src/store.rs | 4 ++-- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 8 +++---- crates/tinywasm/tests/testsuite/run.rs | 4 ++-- 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index 2d5a87f..c4757a4 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -1,5 +1,6 @@ use alloc::string::String; use core::fmt::Display; +use tinywasm_types::FuncType; #[cfg(feature = "parser")] use tinywasm_parser::ParseError; @@ -43,6 +44,26 @@ pub enum Trap { /// Call stack overflow CallStackOverflow, + + /// An undefined element was encountered + UndefinedElement { + /// The element index + index: usize, + }, + + /// An uninitialized element was encountered + UninitializedElement { + /// The element index + index: usize, + }, + + /// Indirect call type mismatch + IndirectCallTypeMismatch { + /// The expected type + expected: FuncType, + /// The actual type + actual: FuncType, + }, } impl Trap { @@ -56,6 +77,9 @@ impl Trap { Self::InvalidConversionToInt => "invalid conversion to integer", Self::IntegerOverflow => "integer overflow", Self::CallStackOverflow => "call stack exhausted", + Self::UndefinedElement { .. } => "undefined element", + Self::UninitializedElement { .. } => "uninitialized element", + Self::IndirectCallTypeMismatch { .. } => "indirect call type mismatch", } } } diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 4b0a328..d6189d2 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -4,7 +4,7 @@ use super::{DefaultRuntime, Stack}; use crate::{ log::debug, runtime::{BlockType, LabelFrame}, - CallFrame, Error, LabelArgs, ModuleInstance, Result, Store, + CallFrame, Error, LabelArgs, ModuleInstance, Result, Store, Trap, }; use alloc::{string::ToString, vec::Vec}; use tinywasm_types::Instruction; @@ -146,10 +146,12 @@ fn exec_one( return Ok(ExecResult::Call); } - CallIndirect(_type_addr, table_addr) => { + CallIndirect(type_addr, table_addr) => { let table_idx = module.resolve_table_addr(*table_addr); let table = store.get_table(table_idx as usize)?; + let call_ty = module.func_ty(*type_addr); + let func_idx = stack.values.pop_t::()?; let func_addr = table.borrow().get(func_idx as usize)?; @@ -157,6 +159,14 @@ fn exec_one( let func = store.get_func(func_addr as usize)?; let func_ty = module.func_ty(func.ty_addr()); + if func_ty != call_ty { + return Err(Trap::IndirectCallTypeMismatch { + actual: func_ty.clone(), + expected: call_ty.clone(), + } + .into()); + } + let params = stack.values.pop_n(func_ty.params.len())?; let call_frame = CallFrame::new_raw(func_addr as usize, ¶ms, func.locals().to_vec()); diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index b425554..563dd8b 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -13,7 +13,7 @@ use tinywasm_types::{ use crate::{ runtime::{self, DefaultRuntime}, - Error, Extern, LinkedImports, ModuleInstance, RawWasmValue, Result, + Error, Extern, LinkedImports, ModuleInstance, RawWasmValue, Result, Trap, }; // global store id counter @@ -437,7 +437,7 @@ impl TableInstance { self.elements .get(addr) .copied() - .ok_or_else(|| Error::Other(format!("table element {} not found", addr))) + .ok_or_else(|| Trap::UndefinedElement { index: addr }.into()) } pub(crate) fn set(&mut self, addr: usize, value: Addr) -> Result<()> { diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index b1a0adc..8e32549 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19566,662,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":75,"failed":16},{"name":"call_indirect.wast","passed":142,"failed":28},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":25,"failed":11},{"name":"global.wast","passed":94,"failed":16},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":94,"failed":2},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19595,633,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":159,"failed":11},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":31,"failed":5},{"name":"global.wast","passed":95,"failed":15},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":116,"failed":32},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index bbfe15b..ed5df2e 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (19567) +v0.3.0-alpha.0 (19595) - - - + + + diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 8b31a88..3e42390 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -251,12 +251,12 @@ impl TestSuite { Ok(Err(err)) => test_group.add_result( &format!("AssertTrap({})", i), span.linecol_in(wast), - Err(eyre!("expected trap, got error: {:?}", err,)), + Err(eyre!("expected trap, {}, got: {:?}", message, err)), ), Ok(Ok(())) => test_group.add_result( &format!("AssertTrap({})", i), span.linecol_in(wast), - Err(eyre!("expected trap, got ok")), + Err(eyre!("expected trap {}, got Ok", message)), ), } } From d466d376c2b08fd60599cfb0697c7cb3dd327207 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 18 Jan 2024 13:46:11 +0100 Subject: [PATCH 12/52] feat: Trunc opcodes Signed-off-by: Henry Gressmann --- crates/tinywasm/src/runtime/executor/macros.rs | 6 ++++++ crates/tinywasm/src/runtime/executor/mod.rs | 9 +++++++++ crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/generated/progress-mvp.svg | 8 ++++---- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/crates/tinywasm/src/runtime/executor/macros.rs b/crates/tinywasm/src/runtime/executor/macros.rs index 48c50f4..c1bb50f 100644 --- a/crates/tinywasm/src/runtime/executor/macros.rs +++ b/crates/tinywasm/src/runtime/executor/macros.rs @@ -198,6 +198,12 @@ macro_rules! arithmetic_single { let result = a.$op(); $stack.values.push((result as $ty).into()); }}; + + ($op:ident, $from:ty, $to:ty, $stack:ident) => {{ + let a: $from = $stack.values.pop()?.into(); + let result = a.$op(); + $stack.values.push((result as $to).into()); + }}; } /// Apply an arithmetic operation to two values on the stack with error checking diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index d6189d2..3df4498 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -555,6 +555,15 @@ fn exec_one( stack.values.push(table.borrow().size().into()); } + I32TruncSatF32S => arithmetic_single!(trunc, f32, i32, stack), + I32TruncSatF32U => arithmetic_single!(trunc, f32, u32, stack), + I32TruncSatF64S => arithmetic_single!(trunc, f64, i32, stack), + I32TruncSatF64U => arithmetic_single!(trunc, f64, u32, stack), + I64TruncSatF32S => arithmetic_single!(trunc, f32, i64, stack), + I64TruncSatF32U => arithmetic_single!(trunc, f32, u64, stack), + I64TruncSatF64S => arithmetic_single!(trunc, f64, i64, stack), + I64TruncSatF64U => arithmetic_single!(trunc, f64, u64, stack), + i => { log::error!("unimplemented instruction: {:?}", i); return Err(Error::UnsupportedFeature(alloc::format!( diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 8e32549..344b8fb 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19595,633,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":159,"failed":11},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":31,"failed":5},{"name":"global.wast","passed":95,"failed":15},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":116,"failed":32},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19775,453,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":159,"failed":11},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":31,"failed":5},{"name":"global.wast","passed":95,"failed":15},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":116,"failed":32},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index ed5df2e..5e3f57b 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (19595) +v0.3.0-alpha.0 (19775) - - - + + + From be396125fe5a3643a91caa35a228ec0390ae1d5f Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 18 Jan 2024 14:52:19 +0100 Subject: [PATCH 13/52] chore: fix a couple of failing tests Signed-off-by: Henry Gressmann --- Cargo.lock | 28 ++++++++++----------- crates/tinywasm/src/imports.rs | 22 ++++++++-------- crates/tinywasm/src/runtime/executor/mod.rs | 7 ++---- crates/tinywasm/src/runtime/value.rs | 2 +- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/testsuite/run.rs | 7 ++---- crates/tinywasm/tests/testsuite/util.rs | 11 +++++++- crates/types/src/lib.rs | 2 ++ 8 files changed, 44 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acd3d65..67a12d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,9 +112,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitvec" @@ -381,9 +381,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -414,9 +414,9 @@ dependencies = [ [[package]] name = "fdeflate" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209098dd6dfc4445aa6111f0e98653ac323eaa4dfd212c9ca3931bf9955c31bd" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] @@ -565,9 +565,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "humantime" @@ -690,16 +690,16 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall", ] [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" @@ -780,9 +780,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "plotters" @@ -1040,7 +1040,7 @@ version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 3a8f393..9059f29 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -168,12 +168,14 @@ impl Imports { name: import.name.to_string(), })?; - let export = module.exports().get_untyped(&import.name.to_string()).ok_or_else(|| { - crate::Error::CouldNotResolveImport { - module: import.module.to_string(), - name: import.name.to_string(), - } - })?; + let export = + module + .exports() + .get_untyped(&import.name) + .ok_or_else(|| crate::Error::CouldNotResolveImport { + module: import.module.to_string(), + name: import.name.to_string(), + })?; // validate import if export.kind != (&import.kind).into() { @@ -184,10 +186,10 @@ impl Imports { } let val = match export.kind { - ExternalKind::Func => ExternVal::Func(export.index.clone()), - ExternalKind::Global => ExternVal::Global(export.index.clone()), - ExternalKind::Table => ExternVal::Table(export.index.clone()), - ExternalKind::Memory => ExternVal::Mem(export.index.clone()), + ExternalKind::Func => ExternVal::Func(export.index), + ExternalKind::Global => ExternVal::Global(export.index), + ExternalKind::Table => ExternVal::Table(export.index), + ExternalKind::Memory => ExternVal::Mem(export.index), }; links.insert( diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 3df4498..95a0a48 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -110,11 +110,8 @@ fn exec_one( Nop => { /* do nothing */ } Unreachable => return Ok(ExecResult::Trap(crate::Trap::Unreachable)), // we don't need to include the call frame here because it's already on the stack Drop => stack.values.pop().map(|_| ())?, - Select(t) => { - if t.is_some() { - unimplemented!("select with type"); - } - + Select(_) => { + // due to validation, we know that the type of the values on the stack let cond: i32 = stack.values.pop()?.into(); let val2 = stack.values.pop()?; diff --git a/crates/tinywasm/src/runtime/value.rs b/crates/tinywasm/src/runtime/value.rs index fec1214..9b0b074 100644 --- a/crates/tinywasm/src/runtime/value.rs +++ b/crates/tinywasm/src/runtime/value.rs @@ -77,4 +77,4 @@ impl_from_raw_wasm_value!(f64, f64::to_bits, f64::from_bits); impl_from_raw_wasm_value!(i8, |x| x as u64, |x| x as i8); impl_from_raw_wasm_value!(i16, |x| x as u64, |x| x as i16); impl_from_raw_wasm_value!(u32, |x| x as u64, |x| x as u32); -impl_from_raw_wasm_value!(u64, |x| x as u64, |x| x as u64); +impl_from_raw_wasm_value!(u64, |x| x, |x| x); diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 344b8fb..7749a65 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19775,453,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":159,"failed":11},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":31,"failed":5},{"name":"global.wast","passed":95,"failed":15},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":116,"failed":32},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19806,422,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":159,"failed":11},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":31,"failed":5},{"name":"global.wast","passed":96,"failed":14},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":143,"failed":5},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 3e42390..462149e 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -1,13 +1,10 @@ use crate::testsuite::util::*; -use std::{ - borrow::Cow, - panic::{catch_unwind, AssertUnwindSafe}, -}; +use std::borrow::Cow; use super::TestSuite; use eyre::{eyre, Result}; use log::{debug, error, info}; -use tinywasm::{Extern, Imports, ModuleInstance, Trap}; +use tinywasm::{Extern, Imports, ModuleInstance}; use tinywasm_types::{MemoryType, ModuleInstanceAddr, TableType, ValType, WasmValue}; use wast::{lexer::Lexer, parser::ParseBuffer, Wast}; diff --git a/crates/tinywasm/tests/testsuite/util.rs b/crates/tinywasm/tests/testsuite/util.rs index 99b94d4..17bca76 100644 --- a/crates/tinywasm/tests/testsuite/util.rs +++ b/crates/tinywasm/tests/testsuite/util.rs @@ -94,7 +94,16 @@ pub fn wastret2tinywasmvalue(arg: wast::WastRet) -> Result nanpattern2tinywasmvalue(f)?, I32(i) => WasmValue::I32(i), I64(i) => WasmValue::I64(i), - _ => return Err(eyre!("unsupported arg type")), + RefNull(t) => WasmValue::RefNull(match t { + Some(wast::core::HeapType::Func) => tinywasm_types::ValType::FuncRef, + Some(wast::core::HeapType::Extern) => tinywasm_types::ValType::ExternRef, + _ => return Err(eyre!("unsupported arg type: refnull: {:?}", t)), + }), + RefExtern(v) => match v { + Some(v) => WasmValue::RefExtern(v), + None => WasmValue::RefNull(tinywasm_types::ValType::ExternRef), + }, + a => return Err(eyre!("unsupported arg type {:?}", a)), }) } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 63f0133..1eef0a5 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -124,6 +124,8 @@ impl WasmValue { match (self, other) { (Self::I32(a), Self::I32(b)) => a == b, (Self::I64(a), Self::I64(b)) => a == b, + (Self::RefNull(ty), Self::RefNull(ty2)) => ty == ty2, + (Self::RefExtern(addr), Self::RefExtern(addr2)) => addr == addr2, (Self::F32(a), Self::F32(b)) => { if a.is_nan() && b.is_nan() { true // Both are NaN, treat them as equal From 032d2cdd590c1cdd30490384742a90dc0c759176 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Sat, 20 Jan 2024 17:53:59 +0100 Subject: [PATCH 14/52] chore: progress towards host functions Signed-off-by: Henry Gressmann --- crates/parser/src/lib.rs | 12 ++++--- crates/tinywasm/src/func.rs | 8 +++-- crates/tinywasm/src/imports.rs | 14 ++++++-- crates/tinywasm/src/runtime/executor/mod.rs | 40 +++++++++++++++------ crates/tinywasm/src/store.rs | 29 ++++++++------- crates/types/src/lib.rs | 27 ++++++++++++-- 6 files changed, 92 insertions(+), 38 deletions(-) diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 561d5c6..3667f1d 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -23,7 +23,7 @@ mod module; use alloc::vec::Vec; pub use error::*; use module::ModuleReader; -use tinywasm_types::Function; +use tinywasm_types::{Function, WasmFunction}; use wasmparser::Validator; pub use tinywasm_types::TinyWasmModule; @@ -108,10 +108,12 @@ impl TryFrom for TinyWasmModule { .code .into_iter() .zip(func_types) - .map(|(f, ty)| Function { - instructions: f.body, - locals: f.locals, - ty, + .map(|(f, ty)| { + Function::WasmFunction(WasmFunction { + instructions: f.body, + locals: f.locals, + ty, + }) }) .collect::>(); diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index e422d25..ef07bf0 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -1,6 +1,6 @@ use alloc::{format, string::String, string::ToString, vec, vec::Vec}; use log::{debug, info}; -use tinywasm_types::{FuncAddr, FuncType, WasmValue}; +use tinywasm_types::{FuncAddr, FuncType, Function, WasmValue}; use crate::{ runtime::{CallFrame, Stack}, @@ -52,9 +52,11 @@ impl FuncHandle { } } + let wasm_func = &func_inst.assert_wasm()?; + // 6. Let f be the dummy frame - debug!("locals: {:?}", func_inst.locals()); - let call_frame = CallFrame::new(self.addr as usize, params, func_inst.locals().to_vec()); + debug!("locals: {:?}", wasm_func.locals); + let call_frame = CallFrame::new(self.addr as usize, params, wasm_func.locals.to_vec()); // 7. Push the frame f to the call stack // & 8. Push the values to the stack (Not needed since the call frame owns the values) diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 9059f29..aa9add1 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -3,7 +3,9 @@ use alloc::{ collections::BTreeMap, string::{String, ToString}, }; -use tinywasm_types::{ExternVal, ExternalKind, GlobalType, MemoryType, ModuleInstanceAddr, TableType, WasmValue}; +use tinywasm_types::{ + ExternVal, ExternalKind, FuncAddr, GlobalType, MemoryType, ModuleInstanceAddr, TableType, WasmValue, +}; #[derive(Debug)] #[non_exhaustive] @@ -19,7 +21,13 @@ pub enum Extern { Memory(ExternMemory), /// A function - Func, + Func(ExternFunc), +} + +/// A function +#[derive(Debug)] +pub struct ExternFunc { + pub(crate) addr: FuncAddr, } /// A global value @@ -69,7 +77,7 @@ impl Extern { Self::Global(_) => ExternalKind::Global, Self::Table(_) => ExternalKind::Table, Self::Memory(_) => ExternalKind::Memory, - Self::Func => ExternalKind::Func, + Self::Func(_) => ExternalKind::Func, } } } diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 95a0a48..e494a27 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -7,7 +7,7 @@ use crate::{ CallFrame, Error, LabelArgs, ModuleInstance, Result, Store, Trap, }; use alloc::{string::ToString, vec::Vec}; -use tinywasm_types::Instruction; +use tinywasm_types::{Function, Instruction}; mod macros; mod traits; @@ -25,8 +25,9 @@ impl DefaultRuntime { let mut cf = stack.call_stack.pop()?; // The function to execute, gets updated from ExecResult::Call - let mut func = store.get_func(cf.func_ptr)?.clone(); - let mut instrs = func.instructions(); + let mut func_inst = store.get_func(cf.func_ptr)?.clone(); + let mut wasm_func = func_inst.assert_wasm()?; + let mut instrs = &wasm_func.instructions; // TODO: we might be able to index into the instructions directly // since the instruction pointer should always be in bounds @@ -35,8 +36,9 @@ impl DefaultRuntime { // Continue execution at the new top of the call stack ExecResult::Call => { cf = stack.call_stack.pop()?; - func = store.get_func(cf.func_ptr)?.clone(); - instrs = func.instructions(); + func_inst = store.get_func(cf.func_ptr)?.clone(); + wasm_func = func_inst.assert_wasm()?; + instrs = &wasm_func.instructions; continue; } @@ -126,13 +128,19 @@ fn exec_one( debug!("start call"); // prepare the call frame let func_idx = module.resolve_func_addr(*v); - let func = store.get_func(func_idx as usize)?; - let func_ty = module.func_ty(func.ty_addr()); + let func_inst = store.get_func(func_idx as usize)?; + let func_ty = module.func_ty(func_inst.ty_addr()); debug!("params: {:?}", func_ty.params); debug!("stack: {:?}", stack.values); let params = stack.values.pop_n(func_ty.params.len())?; - let call_frame = CallFrame::new_raw(*v as usize, ¶ms, func.locals().to_vec()); + + let func = match &func_inst.func { + Function::WasmFunction(wasm_func) => wasm_func, + _ => return Err(Error::UnsupportedFeature("Host functions cannot be called".to_string())), + }; + + let call_frame = CallFrame::new_raw(*v as usize, ¶ms, func.locals.to_vec()); // push the call frame cf.instr_ptr += 1; // skip the call instruction @@ -153,8 +161,8 @@ fn exec_one( let func_addr = table.borrow().get(func_idx as usize)?; // prepare the call frame - let func = store.get_func(func_addr as usize)?; - let func_ty = module.func_ty(func.ty_addr()); + let func_inst = store.get_func(func_addr as usize)?; + let func_ty = module.func_ty(func_inst.ty_addr()); if func_ty != call_ty { return Err(Trap::IndirectCallTypeMismatch { @@ -165,7 +173,17 @@ fn exec_one( } let params = stack.values.pop_n(func_ty.params.len())?; - let call_frame = CallFrame::new_raw(func_addr as usize, ¶ms, func.locals().to_vec()); + + let func = match &func_inst.func { + Function::WasmFunction(wasm_func) => wasm_func, + _ => { + return Err(Error::UnsupportedFeature( + "Host functions cannot be called indirectly".to_string(), + )) + } + }; + + let call_frame = CallFrame::new_raw(func_addr as usize, ¶ms, func.locals.to_vec()); // push the call frame cf.instr_ptr += 1; // skip the call instruction diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 563dd8b..9c8a75e 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -8,7 +8,7 @@ use core::{ use alloc::{format, rc::Rc, string::ToString, vec, vec::Vec}; use tinywasm_types::{ Addr, Data, Element, ElementKind, FuncAddr, Function, Global, GlobalType, Import, Instruction, MemAddr, MemoryArch, - MemoryType, ModuleInstanceAddr, TableAddr, TableType, TypeAddr, ValType, + MemoryType, ModuleInstanceAddr, TableAddr, TableType, TypeAddr, ValType, WasmFunction, }; use crate::{ @@ -393,24 +393,27 @@ impl Store { /// See pub struct FunctionInstance { pub(crate) func: Function, - pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions } -impl FunctionInstance { - pub(crate) fn _module_instance_addr(&self) -> ModuleInstanceAddr { - self.owner - } - - pub(crate) fn locals(&self) -> &[ValType] { - &self.func.locals - } +// TODO: check if this actually helps +#[inline(always)] +#[cold] +const fn cold() {} - pub(crate) fn instructions(&self) -> &[Instruction] { - &self.func.instructions +impl FunctionInstance { + pub(crate) fn assert_wasm(&self) -> Result<&WasmFunction> { + match &self.func { + Function::WasmFunction(w) => Ok(w), + Function::HostFunction(_) => { + cold(); + Err(Error::Other("expected wasm function".to_string())) + } + } } pub(crate) fn ty_addr(&self) -> TypeAddr { - self.func.ty + self.func.ty() } } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 1eef0a5..5b290ca 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -339,12 +339,33 @@ impl FuncType { } } -/// A WebAssembly Function +// A WebAssembly Function #[derive(Debug, Clone)] -pub struct Function { +pub enum Function { + WasmFunction(WasmFunction), + HostFunction(HostFunction), +} + +impl Function { + pub fn ty(&self) -> TypeAddr { + match self { + Self::WasmFunction(f) => f.ty, + Self::HostFunction(f) => f.ty, + } + } +} + +#[derive(Debug, Clone)] +pub struct WasmFunction { pub ty: TypeAddr, - pub locals: Box<[ValType]>, pub instructions: Box<[Instruction]>, + pub locals: Box<[ValType]>, +} + +#[derive(Debug, Clone)] +pub struct HostFunction { + pub ty: TypeAddr, + pub func: fn(&mut [WasmValue]) -> Result<(), ()>, } /// A WebAssembly Module Export From 7b456a58f70c0a1dbaf289d285b14a6b139495f7 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Sat, 20 Jan 2024 19:26:44 +0100 Subject: [PATCH 15/52] feat: typed host funcs Signed-off-by: Henry Gressmann --- crates/parser/src/lib.rs | 12 +-- crates/tinywasm/src/func.rs | 107 +++++++++++++++++++- crates/tinywasm/src/imports.rs | 75 +++++++++++++- crates/tinywasm/src/instance.rs | 10 +- crates/tinywasm/src/runtime/executor/mod.rs | 22 +--- crates/tinywasm/src/store.rs | 19 ++-- crates/tinywasm/tests/testsuite/run.rs | 47 ++++++++- crates/types/src/lib.rs | 34 +------ 8 files changed, 248 insertions(+), 78 deletions(-) diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 3667f1d..0618683 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -23,7 +23,7 @@ mod module; use alloc::vec::Vec; pub use error::*; use module::ModuleReader; -use tinywasm_types::{Function, WasmFunction}; +use tinywasm_types::WasmFunction; use wasmparser::Validator; pub use tinywasm_types::TinyWasmModule; @@ -108,12 +108,10 @@ impl TryFrom for TinyWasmModule { .code .into_iter() .zip(func_types) - .map(|(f, ty)| { - Function::WasmFunction(WasmFunction { - instructions: f.body, - locals: f.locals, - ty, - }) + .map(|(f, ty)| WasmFunction { + instructions: f.body, + locals: f.locals, + ty_addr: ty, }) .collect::>(); diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index ef07bf0..74043a9 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -1,6 +1,6 @@ -use alloc::{format, string::String, string::ToString, vec, vec::Vec}; +use alloc::{boxed::Box, format, string::String, string::ToString, vec, vec::Vec}; use log::{debug, info}; -use tinywasm_types::{FuncAddr, FuncType, Function, WasmValue}; +use tinywasm_types::{FuncAddr, FuncType, ValType, WasmValue}; use crate::{ runtime::{CallFrame, Stack}, @@ -130,6 +130,21 @@ macro_rules! impl_into_wasm_value_tuple { } } +macro_rules! impl_into_wasm_value_tuple_single { + ($T:ident) => { + impl IntoWasmValueTuple for $T { + fn into_wasm_value_tuple(self) -> Vec { + vec![self.into()] + } + } + }; +} + +impl_into_wasm_value_tuple_single!(i32); +impl_into_wasm_value_tuple_single!(i64); +impl_into_wasm_value_tuple_single!(f32); +impl_into_wasm_value_tuple_single!(f64); + impl_into_wasm_value_tuple!(); impl_into_wasm_value_tuple!(T1); impl_into_wasm_value_tuple!(T1, T2); @@ -163,6 +178,27 @@ macro_rules! impl_from_wasm_value_tuple { } } +macro_rules! impl_from_wasm_value_tuple_single { + ($T:ident) => { + impl FromWasmValueTuple for $T { + fn from_wasm_value_tuple(values: Vec) -> Result { + #[allow(unused_variables, unused_mut)] + let mut iter = values.into_iter(); + Ok($T::try_from( + iter.next() + .ok_or(Error::Other("Not enough values in WasmValue vector".to_string()))?, + ) + .map_err(|_| Error::Other("Could not convert WasmValue to expected type".to_string()))?) + } + } + }; +} + +impl_from_wasm_value_tuple_single!(i32); +impl_from_wasm_value_tuple_single!(i64); +impl_from_wasm_value_tuple_single!(f32); +impl_from_wasm_value_tuple_single!(f64); + impl_from_wasm_value_tuple!(); impl_from_wasm_value_tuple!(T1); impl_from_wasm_value_tuple!(T1, T2); @@ -172,3 +208,70 @@ impl_from_wasm_value_tuple!(T1, T2, T3, T4, T5); impl_from_wasm_value_tuple!(T1, T2, T3, T4, T5, T6); impl_from_wasm_value_tuple!(T1, T2, T3, T4, T5, T6, T7); impl_from_wasm_value_tuple!(T1, T2, T3, T4, T5, T6, T7, T8); + +pub trait ValTypesFromTuple { + fn val_types() -> Box<[ValType]>; +} + +pub trait ToValType { + fn to_val_type() -> ValType; +} + +impl ToValType for i32 { + fn to_val_type() -> ValType { + ValType::I32 + } +} + +impl ToValType for i64 { + fn to_val_type() -> ValType { + ValType::I64 + } +} + +impl ToValType for f32 { + fn to_val_type() -> ValType { + ValType::F32 + } +} + +impl ToValType for f64 { + fn to_val_type() -> ValType { + ValType::F64 + } +} + +macro_rules! impl_val_types_from_tuple { + ($($t:ident),+) => { + impl<$($t),+> ValTypesFromTuple for ($($t,)+) + where + $($t: ToValType,)+ + { + fn val_types() -> Box<[ValType]> { + Box::new([$($t::to_val_type(),)+]) + } + } + }; +} + +impl ValTypesFromTuple for () { + fn val_types() -> Box<[ValType]> { + Box::new([]) + } +} + +impl ValTypesFromTuple for T1 +where + T1: ToValType, +{ + fn val_types() -> Box<[ValType]> { + Box::new([T1::to_val_type()]) + } +} + +impl_val_types_from_tuple!(T1); +impl_val_types_from_tuple!(T1, T2); +impl_val_types_from_tuple!(T1, T2, T3); +impl_val_types_from_tuple!(T1, T2, T3, T4); +impl_val_types_from_tuple!(T1, T2, T3, T4, T5); +impl_val_types_from_tuple!(T1, T2, T3, T4, T5, T6); diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index aa9add1..41dd1a2 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -1,12 +1,40 @@ -use crate::Result; +use core::fmt::Debug; + +use crate::{ + func::{FromWasmValueTuple, IntoWasmValueTuple, ValTypesFromTuple}, + Result, +}; use alloc::{ collections::BTreeMap, string::{String, ToString}, + sync::Arc, + vec::Vec, }; use tinywasm_types::{ - ExternVal, ExternalKind, FuncAddr, GlobalType, MemoryType, ModuleInstanceAddr, TableType, WasmValue, + ExternVal, ExternalKind, GlobalType, MemoryType, ModuleInstanceAddr, TableType, WasmFunction, WasmValue, }; +#[derive(Debug)] +pub(crate) enum Function { + Host(HostFunction), + Wasm(WasmFunction), +} + +/// A host function +pub struct HostFunction { + pub(crate) ty: tinywasm_types::FuncType, + pub(crate) func: Arc Result> + 'static + Send + Sync>, +} + +impl Debug for HostFunction { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("HostFunction") + .field("ty", &self.ty) + .field("func", &"...") + .finish() + } +} + #[derive(Debug)] #[non_exhaustive] /// An external value @@ -21,13 +49,13 @@ pub enum Extern { Memory(ExternMemory), /// A function - Func(ExternFunc), + Func(HostFunction), } /// A function #[derive(Debug)] pub struct ExternFunc { - pub(crate) addr: FuncAddr, + pub(crate) inner: HostFunction, } /// A global value @@ -72,6 +100,45 @@ impl Extern { Self::Memory(ExternMemory { ty }) } + /// Create a new function import + pub fn func( + ty: &tinywasm_types::FuncType, + func: impl Fn(&mut crate::Store, &[WasmValue]) -> Result> + 'static + Send + Sync, + ) -> Self { + let inner_func = move |store: &mut crate::Store, args: &[WasmValue]| { + let args = args.to_vec(); + func(store, &args) + }; + + Self::Func(HostFunction { + func: Arc::new(inner_func), + ty: ty.clone(), + }) + } + + /// Create a new typed function import + pub fn typed_func(func: impl Fn(&mut crate::Store, P) -> Result + 'static + Send + Sync) -> Self + where + P: FromWasmValueTuple + ValTypesFromTuple, + R: IntoWasmValueTuple + ValTypesFromTuple, + { + let inner_func = move |store: &mut crate::Store, args: &[WasmValue]| -> Result> { + let args = P::from_wasm_value_tuple(args.to_vec())?; + let result = func(store, args)?; + Ok(result.into_wasm_value_tuple()) + }; + + let ty = tinywasm_types::FuncType { + params: P::val_types(), + results: R::val_types(), + }; + + Self::Func(HostFunction { + func: Arc::new(inner_func), + ty: ty.clone(), + }) + } + pub(crate) fn kind(&self) -> ExternalKind { match self { Self::Global(_) => ExternalKind::Global, diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 7fd30aa..ad1b53c 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -153,8 +153,9 @@ impl ModuleInstance { .ok_or_else(|| Error::Other(format!("Export not found: {}", name)))?; let func_addr = self.0.func_addrs[export.index as usize]; - let func = store.get_func(func_addr as usize)?; - let ty = self.0.types[func.ty_addr() as usize].clone(); + let func_inst = store.get_func(func_addr as usize)?; + let func = func_inst.assert_wasm()?; + let ty = self.0.types[func.ty_addr as usize].clone(); Ok(FuncHandle { addr: export.index, @@ -207,8 +208,9 @@ impl ModuleInstance { .get(func_index as usize) .expect("No func addr for start func, this is a bug"); - let func = store.get_func(*func_addr as usize)?; - let ty = self.0.types[func.ty_addr() as usize].clone(); + let func_inst = store.get_func(*func_addr as usize)?; + let func = func_inst.assert_wasm()?; + let ty = self.0.types[func.ty_addr as usize].clone(); Ok(Some(FuncHandle { module: self.clone(), diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index e494a27..5e191cc 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -7,7 +7,7 @@ use crate::{ CallFrame, Error, LabelArgs, ModuleInstance, Result, Store, Trap, }; use alloc::{string::ToString, vec::Vec}; -use tinywasm_types::{Function, Instruction}; +use tinywasm_types::Instruction; mod macros; mod traits; @@ -129,17 +129,13 @@ fn exec_one( // prepare the call frame let func_idx = module.resolve_func_addr(*v); let func_inst = store.get_func(func_idx as usize)?; - let func_ty = module.func_ty(func_inst.ty_addr()); + let func = func_inst.assert_wasm()?; + let func_ty = module.func_ty(func.ty_addr); debug!("params: {:?}", func_ty.params); debug!("stack: {:?}", stack.values); let params = stack.values.pop_n(func_ty.params.len())?; - let func = match &func_inst.func { - Function::WasmFunction(wasm_func) => wasm_func, - _ => return Err(Error::UnsupportedFeature("Host functions cannot be called".to_string())), - }; - let call_frame = CallFrame::new_raw(*v as usize, ¶ms, func.locals.to_vec()); // push the call frame @@ -162,7 +158,8 @@ fn exec_one( // prepare the call frame let func_inst = store.get_func(func_addr as usize)?; - let func_ty = module.func_ty(func_inst.ty_addr()); + let func = func_inst.assert_wasm()?; + let func_ty = module.func_ty(func.ty_addr); if func_ty != call_ty { return Err(Trap::IndirectCallTypeMismatch { @@ -174,15 +171,6 @@ fn exec_one( let params = stack.values.pop_n(func_ty.params.len())?; - let func = match &func_inst.func { - Function::WasmFunction(wasm_func) => wasm_func, - _ => { - return Err(Error::UnsupportedFeature( - "Host functions cannot be called indirectly".to_string(), - )) - } - }; - let call_frame = CallFrame::new_raw(func_addr as usize, ¶ms, func.locals.to_vec()); // push the call frame diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 9c8a75e..6293cca 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -7,13 +7,13 @@ use core::{ use alloc::{format, rc::Rc, string::ToString, vec, vec::Vec}; use tinywasm_types::{ - Addr, Data, Element, ElementKind, FuncAddr, Function, Global, GlobalType, Import, Instruction, MemAddr, MemoryArch, + Addr, Data, Element, ElementKind, FuncAddr, Global, GlobalType, Import, Instruction, MemAddr, MemoryArch, MemoryType, ModuleInstanceAddr, TableAddr, TableType, TypeAddr, ValType, WasmFunction, }; use crate::{ runtime::{self, DefaultRuntime}, - Error, Extern, LinkedImports, ModuleInstance, RawWasmValue, Result, Trap, + Error, Extern, Function, LinkedImports, ModuleInstance, RawWasmValue, Result, Trap, }; // global store id counter @@ -114,11 +114,14 @@ impl Store { } /// Add functions to the store, returning their addresses in the store - pub(crate) fn add_funcs(&mut self, funcs: Vec, idx: ModuleInstanceAddr) -> Vec { + pub(crate) fn add_funcs(&mut self, funcs: Vec, idx: ModuleInstanceAddr) -> Vec { let func_count = self.data.funcs.len(); let mut func_addrs = Vec::with_capacity(func_count); for (i, func) in funcs.into_iter().enumerate() { - self.data.funcs.push(Rc::new(FunctionInstance { func, owner: idx })); + self.data.funcs.push(Rc::new(FunctionInstance { + func: Function::Wasm(func), + owner: idx, + })); func_addrs.push((i + func_count) as FuncAddr); } func_addrs @@ -404,17 +407,13 @@ const fn cold() {} impl FunctionInstance { pub(crate) fn assert_wasm(&self) -> Result<&WasmFunction> { match &self.func { - Function::WasmFunction(w) => Ok(w), - Function::HostFunction(_) => { + Function::Wasm(w) => Ok(w), + Function::Host(_) => { cold(); Err(Error::Other("expected wasm function".to_string())) } } } - - pub(crate) fn ty_addr(&self) -> TypeAddr { - self.func.ty() - } } /// A WebAssembly Table Instance diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 462149e..5dd42ee 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -22,19 +22,60 @@ impl TestSuite { fn imports(registered_modules: Vec<(String, ModuleInstanceAddr)>) -> Result { let mut imports = Imports::new(); - let memory = Extern::memory(MemoryType::new_32(1, Some(2))); let table = Extern::table( TableType::new(ValType::FuncRef, 10, Some(20)), WasmValue::default_for(ValType::FuncRef), ); + let print = Extern::typed_func(|_: &mut tinywasm::Store, _: ()| { + log::debug!("print"); + Ok(()) + }); + + let print_i32 = Extern::typed_func(|_: &mut tinywasm::Store, arg: i32| { + log::debug!("print_i32: {}", arg); + Ok(()) + }); + + let print_i64 = Extern::typed_func(|_: &mut tinywasm::Store, arg: i64| { + log::debug!("print_i64: {}", arg); + Ok(()) + }); + + let print_f32 = Extern::typed_func(|_: &mut tinywasm::Store, arg: f32| { + log::debug!("print_f32: {}", arg); + Ok(()) + }); + + let print_f64 = Extern::typed_func(|_: &mut tinywasm::Store, arg: f64| { + log::debug!("print_f64: {}", arg); + Ok(()) + }); + + let print_i32_f32 = Extern::typed_func(|_: &mut tinywasm::Store, args: (i32, f32)| { + log::debug!("print_i32_f32: {}, {}", args.0, args.1); + Ok(()) + }); + + let print_i64_f64 = Extern::typed_func(|_: &mut tinywasm::Store, args: (i64, f64)| { + log::debug!("print_i64_f64: {}, {}", args.0, args.1); + Ok(()) + }); + imports - .define("spectest", "memory", memory)? + .define("spectest", "memory", Extern::memory(MemoryType::new_32(1, Some(2))))? .define("spectest", "table", table)? .define("spectest", "global_i32", Extern::global(WasmValue::I32(666), false))? .define("spectest", "global_i64", Extern::global(WasmValue::I64(666), false))? .define("spectest", "global_f32", Extern::global(WasmValue::F32(666.0), false))? - .define("spectest", "global_f64", Extern::global(WasmValue::F64(666.0), false))?; + .define("spectest", "global_f64", Extern::global(WasmValue::F64(666.0), false))? + .define("spectest", "print", print)? + .define("spectest", "print_i32", print_i32)? + .define("spectest", "print_i64", print_i64)? + .define("spectest", "print_f32", print_f32)? + .define("spectest", "print_f64", print_f64)? + .define("spectest", "print_i32_f32", print_i32_f32)? + .define("spectest", "print_i64_f64", print_i64_f64)?; for (name, addr) in registered_modules { imports.link_module(&name, addr)?; diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 5b290ca..069f134 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -28,7 +28,7 @@ extern crate alloc; mod instructions; use core::{fmt::Debug, ops::Range}; -use alloc::boxed::Box; +use alloc::{boxed::Box, sync::Arc, vec::Vec}; pub use instructions::*; /// A TinyWasm WebAssembly Module @@ -45,7 +45,7 @@ pub struct TinyWasmModule { pub start_func: Option, /// The functions of the WebAssembly module. - pub funcs: Box<[Function]>, + pub funcs: Box<[WasmFunction]>, /// The types of the WebAssembly module. pub func_types: Box<[FuncType]>, @@ -169,12 +169,6 @@ impl From for WasmValue { } } -// impl From for WasmValue { -// fn from(i: i128) -> Self { -// Self::V128(i) -// } -// } - impl TryFrom for i32 { type Error = (); @@ -339,35 +333,13 @@ impl FuncType { } } -// A WebAssembly Function -#[derive(Debug, Clone)] -pub enum Function { - WasmFunction(WasmFunction), - HostFunction(HostFunction), -} - -impl Function { - pub fn ty(&self) -> TypeAddr { - match self { - Self::WasmFunction(f) => f.ty, - Self::HostFunction(f) => f.ty, - } - } -} - #[derive(Debug, Clone)] pub struct WasmFunction { - pub ty: TypeAddr, + pub ty_addr: TypeAddr, pub instructions: Box<[Instruction]>, pub locals: Box<[ValType]>, } -#[derive(Debug, Clone)] -pub struct HostFunction { - pub ty: TypeAddr, - pub func: fn(&mut [WasmValue]) -> Result<(), ()>, -} - /// A WebAssembly Module Export #[derive(Debug, Clone)] pub struct Export { From 1b6f5dfc63e2f64aa1c1fed1a6b4c3e1e32db1b9 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Sun, 21 Jan 2024 20:50:27 +0100 Subject: [PATCH 16/52] wip: refactoring imports Signed-off-by: Henry Gressmann --- Cargo.lock | 4 +- crates/tinywasm/src/imports.rs | 223 +++++++++++++++--------- crates/tinywasm/src/instance.rs | 16 +- crates/tinywasm/src/store.rs | 137 +++++++-------- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/testsuite/run.rs | 9 +- crates/types/src/lib.rs | 2 +- 7 files changed, 219 insertions(+), 174 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 67a12d6..0b4e95c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1272,9 +1272,9 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uuid" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" [[package]] name = "version_check" diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 41dd1a2..e7f9b81 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -11,12 +11,17 @@ use alloc::{ vec::Vec, }; use tinywasm_types::{ - ExternVal, ExternalKind, GlobalType, MemoryType, ModuleInstanceAddr, TableType, WasmFunction, WasmValue, + ExternVal, ExternalKind, FuncAddr, GlobalAddr, GlobalType, Import, MemAddr, MemoryType, ModuleInstanceAddr, + TableAddr, TableType, WasmFunction, WasmValue, }; +/// The internal representation of a function #[derive(Debug)] -pub(crate) enum Function { +pub enum Function { + /// A host function Host(HostFunction), + + /// A function defined in WebAssembly Wasm(WasmFunction), } @@ -49,14 +54,12 @@ pub enum Extern { Memory(ExternMemory), /// A function - Func(HostFunction), + Func(Function), } /// A function #[derive(Debug)] -pub struct ExternFunc { - pub(crate) inner: HostFunction, -} +pub struct ExternFunc(pub(crate) HostFunction); /// A global value #[derive(Debug)] @@ -110,10 +113,10 @@ impl Extern { func(store, &args) }; - Self::Func(HostFunction { + Self::Func(Function::Host(HostFunction { func: Arc::new(inner_func), ty: ty.clone(), - }) + })) } /// Create a new typed function import @@ -133,10 +136,10 @@ impl Extern { results: R::val_types(), }; - Self::Func(HostFunction { + Self::Func(Function::Host(HostFunction { func: Arc::new(inner_func), - ty: ty.clone(), - }) + ty, + })) } pub(crate) fn kind(&self) -> ExternalKind { @@ -156,6 +159,15 @@ pub struct ExternName { name: String, } +impl From<&Import> for ExternName { + fn from(import: &Import) -> Self { + Self { + module: import.module.to_string(), + name: import.name.to_string(), + } + } +} + #[derive(Debug, Default)] /// Imports for a module instance pub struct Imports { @@ -163,20 +175,77 @@ pub struct Imports { modules: BTreeMap, } -pub(crate) struct LinkedImports { - // externs that were defined and need to be instantiated - pub(crate) externs: BTreeMap, +pub(crate) enum ResolvedExtern { + // already in the store + Store(S), - // externs that were linked to other modules and already exist in the store - pub(crate) linked_externs: BTreeMap, + // needs to be added to the store, provided value + Extern(V), } -impl LinkedImports { - pub(crate) fn get(&self, module: &str, name: &str) -> Option<&Extern> { - self.externs.get(&ExternName { - module: module.to_string(), - name: name.to_string(), - }) +pub(crate) enum ResolvedImport { + Extern(Extern), + Store(ExternVal), +} + +impl ResolvedImport { + fn initialize(self, store: &mut crate::Store, idx: ModuleInstanceAddr) -> Result { + match self { + Self::Extern(extern_) => match extern_ { + Extern::Global(global) => { + let addr = store.add_global(global.ty, global.val.into(), idx)?; + Ok(ExternVal::Global(addr)) + } + Extern::Table(table) => { + // todo: do something with the initial value + let addr = store.add_table(table.ty, idx)?; + Ok(ExternVal::Table(addr)) + } + Extern::Memory(memory) => { + let addr = store.add_mem(memory.ty, idx)?; + Ok(ExternVal::Mem(addr)) + } + Extern::Func(func) => { + let addr = store.add_func(func, idx)?; + Ok(ExternVal::Func(addr)) + } + }, + Self::Store(extern_val) => Ok(extern_val.clone()), + } + } +} + +pub(crate) struct ResolvedImports { + pub(crate) globals: Vec>, + pub(crate) tables: Vec>, + pub(crate) mems: Vec>, + pub(crate) funcs: Vec>, +} + +impl ResolvedImports { + pub(crate) fn new() -> Self { + Self { + globals: Vec::new(), + tables: Vec::new(), + mems: Vec::new(), + funcs: Vec::new(), + } + } + + pub(crate) fn globals(&self) -> &[ResolvedExtern] { + &self.globals + } + + pub(crate) fn tables(&self) -> &[ResolvedExtern] { + &self.tables + } + + pub(crate) fn mems(&self) -> &[ResolvedExtern] { + &self.mems + } + + pub(crate) fn funcs(&self) -> &[ResolvedExtern] { + &self.funcs } } @@ -209,77 +278,63 @@ impl Imports { Ok(self) } - pub(crate) fn link(self, store: &mut crate::Store, module: &crate::Module) -> Result { - let mut links = BTreeMap::new(); + pub(crate) fn take(&mut self, store: &mut crate::Store, import: &Import) -> Option { + // TODO: compare types - for import in module.data.imports.iter() { - if let Some(i) = self.values.get(&ExternName { - module: import.module.to_string(), - name: import.name.to_string(), - }) { - if i.kind() != (&import.kind).into() { - return Err(crate::Error::InvalidImportType { - module: import.module.to_string(), - name: import.name.to_string(), - }); - } + let name = ExternName::from(import); + if let Some(v) = self.values.remove(&name) { + return Some(ResolvedImport::Extern(v)); + } - continue; - } - - let module_addr = - self.modules - .get(&import.module.to_string()) - .ok_or_else(|| crate::Error::MissingImport { - module: import.module.to_string(), - name: import.name.to_string(), - })?; - - let module = - store - .get_module_instance(*module_addr) - .ok_or_else(|| crate::Error::CouldNotResolveImport { - module: import.module.to_string(), - name: import.name.to_string(), - })?; - - let export = - module - .exports() - .get_untyped(&import.name) - .ok_or_else(|| crate::Error::CouldNotResolveImport { - module: import.module.to_string(), - name: import.name.to_string(), - })?; + return None; - // validate import - if export.kind != (&import.kind).into() { - return Err(crate::Error::InvalidImportType { + // TODO: allow linking to other modules + // if let Some(module_addr) = self.modules.get(&name.module) { + // let Some(module) = store.get_module_instance(*module_addr) else { + // return None; + // }; + + // let export = module.exports().get_untyped(&name.name)?; + // }; + + // then check if the import is defined + } + + pub(crate) fn link(mut self, store: &mut crate::Store, module: &crate::Module) -> Result { + let mut imports = ResolvedImports::new(); + + for import in module.data.imports.iter() { + let Some(val) = self.take(store, import) else { + return Err(crate::Error::MissingImport { module: import.module.to_string(), name: import.name.to_string(), }); - } - - let val = match export.kind { - ExternalKind::Func => ExternVal::Func(export.index), - ExternalKind::Global => ExternVal::Global(export.index), - ExternalKind::Table => ExternVal::Table(export.index), - ExternalKind::Memory => ExternVal::Mem(export.index), }; - links.insert( - ExternName { - module: import.module.to_string(), - name: import.name.to_string(), - }, - val, - ); + // validate import + // if export.kind != (&import.kind).into() { + // return Err(crate::Error::InvalidImportType { + // module: import.module.to_string(), + // name: import.name.to_string(), + // }); + // } + + // let val = match export.kind { + // ExternalKind::Func => ExternVal::Func(export.index), + // ExternalKind::Global => ExternVal::Global(export.index), + // ExternalKind::Table => ExternVal::Table(export.index), + // ExternalKind::Memory => ExternVal::Mem(export.index), + // }; + + // imports.0.insert( + // ExternName { + // module: import.module.to_string(), + // name: import.name.to_string(), + // }, + // ResolvedImport::Store(val), + // ); } - // TODO: link to other modules (currently only direct imports are supported) - Ok(LinkedImports { - externs: self.values, - linked_externs: links, - }) + Ok(imports) } } diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index ad1b53c..b8f87d7 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -52,14 +52,13 @@ impl ModuleInstance { let idx = store.next_module_instance_idx(); let imports = imports.unwrap_or_default(); - // TODO: doesn't link other modules yet let linked_imports = imports.link(store, &module)?; - let global_addrs = store.add_globals(module.data.globals.into(), &module.data.imports, &linked_imports, idx)?; + let global_addrs = store.add_globals(module.data.globals.into(), idx)?; // TODO: imported functions missing - let func_addrs = store.add_funcs(module.data.funcs.into(), idx); + let func_addrs = store.add_funcs(module.data.funcs.into(), idx)?; - let table_addrs = store.add_tables(module.data.table_types.into(), idx); + let table_addrs = store.add_tables(module.data.table_types.into(), idx)?; let mem_addrs = store.add_mems(module.data.memory_types.into(), idx)?; // TODO: active/declared elems need to be initialized @@ -152,8 +151,13 @@ impl ModuleInstance { .get(name, ExternalKind::Func) .ok_or_else(|| Error::Other(format!("Export not found: {}", name)))?; - let func_addr = self.0.func_addrs[export.index as usize]; - let func_inst = store.get_func(func_addr as usize)?; + let func_addr = self + .0 + .func_addrs + .get(export.index as usize) + .expect("No func addr for export, this is a bug"); + + let func_inst = store.get_func(*func_addr as usize)?; let func = func_inst.assert_wasm()?; let ty = self.0.types[func.ty_addr as usize].clone(); diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 6293cca..9b2f711 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -7,13 +7,13 @@ use core::{ use alloc::{format, rc::Rc, string::ToString, vec, vec::Vec}; use tinywasm_types::{ - Addr, Data, Element, ElementKind, FuncAddr, Global, GlobalType, Import, Instruction, MemAddr, MemoryArch, - MemoryType, ModuleInstanceAddr, TableAddr, TableType, TypeAddr, ValType, WasmFunction, + Addr, Data, DataAddr, ElemAddr, Element, ElementKind, FuncAddr, Global, GlobalType, Import, MemAddr, MemoryArch, + MemoryType, ModuleInstanceAddr, TableAddr, TableType, WasmFunction, }; use crate::{ runtime::{self, DefaultRuntime}, - Error, Extern, Function, LinkedImports, ModuleInstance, RawWasmValue, Result, Trap, + Error, Function, ModuleInstance, RawWasmValue, Result, Trap, }; // global store id counter @@ -114,31 +114,23 @@ impl Store { } /// Add functions to the store, returning their addresses in the store - pub(crate) fn add_funcs(&mut self, funcs: Vec, idx: ModuleInstanceAddr) -> Vec { + pub(crate) fn add_funcs(&mut self, funcs: Vec, idx: ModuleInstanceAddr) -> Result> { let func_count = self.data.funcs.len(); let mut func_addrs = Vec::with_capacity(func_count); - for (i, func) in funcs.into_iter().enumerate() { - self.data.funcs.push(Rc::new(FunctionInstance { - func: Function::Wasm(func), - owner: idx, - })); - func_addrs.push((i + func_count) as FuncAddr); + for func in funcs.into_iter() { + func_addrs.push(self.add_func(Function::Wasm(func), idx)?); } - func_addrs + Ok(func_addrs) } /// Add tables to the store, returning their addresses in the store - pub(crate) fn add_tables(&mut self, tables: Vec, idx: ModuleInstanceAddr) -> Vec { + pub(crate) fn add_tables(&mut self, tables: Vec, idx: ModuleInstanceAddr) -> Result> { let table_count = self.data.tables.len(); let mut table_addrs = Vec::with_capacity(table_count); for (i, table) in tables.into_iter().enumerate() { - self.data - .tables - .push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); - - table_addrs.push((i + table_count) as TableAddr); + table_addrs.push(self.add_table(table, idx)?); } - table_addrs + Ok(table_addrs) } /// Add memories to the store, returning their addresses in the store @@ -146,78 +138,71 @@ impl Store { let mem_count = self.data.mems.len(); let mut mem_addrs = Vec::with_capacity(mem_count); for (i, mem) in mems.into_iter().enumerate() { - if let MemoryArch::I64 = mem.arch { - return Err(Error::UnsupportedFeature("64-bit memories".to_string())); - } - self.data - .mems - .push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); - - mem_addrs.push((i + mem_count) as MemAddr); + mem_addrs.push(self.add_mem(mem, idx)?); } Ok(mem_addrs) } /// Add globals to the store, returning their addresses in the store - pub(crate) fn add_globals( - &mut self, - globals: Vec, - wasm_imports: &[Import], - user_imports: &LinkedImports, - idx: ModuleInstanceAddr, - ) -> Result> { - // TODO: initialize imported globals - #![allow(clippy::unnecessary_filter_map)] // this is cleaner - let imported_globals = wasm_imports - .iter() - .filter_map(|import| match &import.kind { - tinywasm_types::ImportKind::Global(_) => Some(import), - _ => None, - }) - .map(|import| { - let Some(global) = user_imports.get(&import.module, &import.name) else { - return Err(Error::Other(format!( - "global import not found for {}::{}", - import.module, import.name - ))); - }; - match global { - Extern::Global(global) => Ok(global), - _ => Err(Error::Other(format!( - "expected global import for {}::{}", - import.module, import.name - ))), - } - }) - .collect::>>()?; - + pub(crate) fn add_globals(&mut self, globals: Vec, idx: ModuleInstanceAddr) -> Result> { let global_count = self.data.globals.len(); let mut global_addrs = Vec::with_capacity(global_count); - log::debug!("globals: {:?}", globals); - - // first add the imported globals - for (i, global) in imported_globals.iter().enumerate() { - self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new( - global.ty, - global.val.into(), - idx, - )))); - global_addrs.push((i + global_count) as Addr); - } - // then add the module globals for (i, global) in globals.iter().enumerate() { - self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new( - global.ty, - self.eval_const(&global.init)?, - idx, - )))); - global_addrs.push((i + global_count) as Addr); + global_addrs.push(self.add_global(global.ty, self.eval_const(&global.init)?, idx)?.into()); } Ok(global_addrs) } + pub(crate) fn add_global(&mut self, ty: GlobalType, value: RawWasmValue, idx: ModuleInstanceAddr) -> Result { + self.data + .globals + .push(Rc::new(RefCell::new(GlobalInstance::new(ty, value, idx)))); + Ok(self.data.globals.len() as Addr - 1) + } + + pub(crate) fn add_table(&mut self, table: TableType, idx: ModuleInstanceAddr) -> Result { + self.data + .tables + .push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); + Ok(self.data.tables.len() as TableAddr - 1) + } + + pub(crate) fn add_mem(&mut self, mem: MemoryType, idx: ModuleInstanceAddr) -> Result { + if let MemoryArch::I64 = mem.arch { + return Err(Error::UnsupportedFeature("64-bit memories".to_string())); + } + self.data + .mems + .push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); + Ok(self.data.mems.len() as MemAddr - 1) + } + + pub(crate) fn add_elem(&mut self, elem: Element, idx: ModuleInstanceAddr) -> Result { + let init = elem + .items + .iter() + .map(|item| { + item.addr() + .ok_or_else(|| Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item))) + }) + .collect::>>()?; + + self.data.elems.push(ElemInstance::new(elem.kind, idx, Some(init))); + Ok(self.data.elems.len() as ElemAddr - 1) + } + + pub(crate) fn add_data(&mut self, data: Data, idx: ModuleInstanceAddr) -> Result { + self.data.datas.push(DataInstance::new(data.data.to_vec(), idx)); + Ok(self.data.datas.len() as DataAddr - 1) + } + + pub(crate) fn add_func(&mut self, func: Function, idx: ModuleInstanceAddr) -> Result { + self.data.funcs.push(Rc::new(FunctionInstance { func, owner: idx })); + Ok(self.data.funcs.len() as FuncAddr - 1) + } + pub(crate) fn eval_i32_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { use tinywasm_types::ConstInstruction::*; let val = match const_instr { diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 7749a65..e175639 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19806,422,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":88,"failed":3},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":159,"failed":11},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":31,"failed":5},{"name":"global.wast","passed":96,"failed":14},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":50,"failed":133},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":143,"failed":5},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":57,"failed":1},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19816,412,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":159,"failed":11},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":32,"failed":4},{"name":"global.wast","passed":96,"failed":14},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":52,"failed":131},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":20,"failed":112},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":143,"failed":5},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 5dd42ee..d2eab6c 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -57,8 +57,8 @@ impl TestSuite { Ok(()) }); - let print_i64_f64 = Extern::typed_func(|_: &mut tinywasm::Store, args: (i64, f64)| { - log::debug!("print_i64_f64: {}, {}", args.0, args.1); + let print_f64_f64 = Extern::typed_func(|_: &mut tinywasm::Store, args: (f64, f64)| { + log::debug!("print_f64_f64: {}, {}", args.0, args.1); Ok(()) }); @@ -75,9 +75,10 @@ impl TestSuite { .define("spectest", "print_f32", print_f32)? .define("spectest", "print_f64", print_f64)? .define("spectest", "print_i32_f32", print_i32_f32)? - .define("spectest", "print_i64_f64", print_i64_f64)?; + .define("spectest", "print_f64_f64", print_f64_f64)?; for (name, addr) in registered_modules { + log::debug!("registering module: {}", name); imports.link_module(&name, addr)?; } @@ -137,7 +138,7 @@ impl TestSuite { Wat(mut module) => { // TODO: modules are not properly isolated from each other - tests fail because of this otherwise - store = tinywasm::Store::default(); + // store = tinywasm::Store::default(); debug!("got wat module"); let result = catch_unwind_silent(|| { let m = parse_module_bytes(&module.encode().expect("failed to encode module")) diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 069f134..ac7f854 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -306,7 +306,7 @@ pub type ModuleInstanceAddr = Addr; /// A WebAssembly External Value. /// /// See -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum ExternVal { Func(FuncAddr), Table(TableAddr), From 1eb6f3160a5c6036926bd3db757d2ff3ca4b1a53 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Sun, 21 Jan 2024 22:27:20 +0100 Subject: [PATCH 17/52] fix export isolation issues Signed-off-by: Henry Gressmann --- Cargo.lock | 12 +- crates/tinywasm/src/export.rs | 17 -- crates/tinywasm/src/imports.rs | 241 ++++++++------------ crates/tinywasm/src/instance.rs | 110 ++++----- crates/tinywasm/src/lib.rs | 8 +- crates/tinywasm/src/runtime/executor/mod.rs | 14 +- crates/tinywasm/src/store.rs | 94 ++------ crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/types/src/lib.rs | 48 ++-- rustfmt.toml | 1 + 10 files changed, 210 insertions(+), 337 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b4e95c..32ebc37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -855,9 +855,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -919,9 +919,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", @@ -931,9 +931,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" dependencies = [ "aho-corasick", "memchr", diff --git a/crates/tinywasm/src/export.rs b/crates/tinywasm/src/export.rs index 52adc6f..8b13789 100644 --- a/crates/tinywasm/src/export.rs +++ b/crates/tinywasm/src/export.rs @@ -1,18 +1 @@ -use alloc::boxed::Box; -use tinywasm_types::{Export, ExternalKind}; -#[derive(Debug)] -/// Exports of a module instance -// TODO: Maybe use a BTreeMap instead? -pub struct ExportInstance(pub(crate) Box<[Export]>); - -impl ExportInstance { - /// Get an export by name - pub fn get(&self, name: &str, ty: ExternalKind) -> Option<&Export> { - self.0.iter().find(|e| e.name == name.into() && e.kind == ty) - } - - pub(crate) fn get_untyped(&self, name: &str) -> Option<&Export> { - self.0.iter().find(|e| e.name == name.into()) - } -} diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index e7f9b81..f89ba64 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -11,12 +11,12 @@ use alloc::{ vec::Vec, }; use tinywasm_types::{ - ExternVal, ExternalKind, FuncAddr, GlobalAddr, GlobalType, Import, MemAddr, MemoryType, ModuleInstanceAddr, - TableAddr, TableType, WasmFunction, WasmValue, + Addr, Export, ExternVal, ExternalKind, FuncAddr, GlobalAddr, GlobalType, Import, MemAddr, MemoryType, + ModuleInstanceAddr, TableAddr, TableType, WasmFunction, WasmValue, }; /// The internal representation of a function -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Function { /// A host function Host(HostFunction), @@ -26,6 +26,7 @@ pub enum Function { } /// A host function +#[derive(Clone)] pub struct HostFunction { pub(crate) ty: tinywasm_types::FuncType, pub(crate) func: Arc Result> + 'static + Send + Sync>, @@ -33,14 +34,11 @@ pub struct HostFunction { impl Debug for HostFunction { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("HostFunction") - .field("ty", &self.ty) - .field("func", &"...") - .finish() + f.debug_struct("HostFunction").field("ty", &self.ty).field("func", &"...").finish() } } -#[derive(Debug)] +#[derive(Debug, Clone)] #[non_exhaustive] /// An external value pub enum Extern { @@ -58,25 +56,25 @@ pub enum Extern { } /// A function -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ExternFunc(pub(crate) HostFunction); /// A global value -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ExternGlobal { pub(crate) ty: GlobalType, pub(crate) val: WasmValue, } /// A table -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ExternTable { pub(crate) ty: TableType, pub(crate) val: WasmValue, } /// A memory -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ExternMemory { pub(crate) ty: MemoryType, } @@ -84,13 +82,7 @@ pub struct ExternMemory { impl Extern { /// Create a new global import pub fn global(val: WasmValue, mutable: bool) -> Self { - Self::Global(ExternGlobal { - ty: GlobalType { - ty: val.val_type(), - mutable, - }, - val, - }) + Self::Global(ExternGlobal { ty: GlobalType { ty: val.val_type(), mutable }, val }) } /// Create a new table import @@ -113,10 +105,7 @@ impl Extern { func(store, &args) }; - Self::Func(Function::Host(HostFunction { - func: Arc::new(inner_func), - ty: ty.clone(), - })) + Self::Func(Function::Host(HostFunction { func: Arc::new(inner_func), ty: ty.clone() })) } /// Create a new typed function import @@ -131,15 +120,9 @@ impl Extern { Ok(result.into_wasm_value_tuple()) }; - let ty = tinywasm_types::FuncType { - params: P::val_types(), - results: R::val_types(), - }; + let ty = tinywasm_types::FuncType { params: P::val_types(), results: R::val_types() }; - Self::Func(Function::Host(HostFunction { - func: Arc::new(inner_func), - ty, - })) + Self::Func(Function::Host(HostFunction { func: Arc::new(inner_func), ty })) } pub(crate) fn kind(&self) -> ExternalKind { @@ -161,10 +144,7 @@ pub struct ExternName { impl From<&Import> for ExternName { fn from(import: &Import) -> Self { - Self { - module: import.module.to_string(), - name: import.name.to_string(), - } + Self { module: import.module.to_string(), name: import.name.to_string() } } } @@ -183,79 +163,23 @@ pub(crate) enum ResolvedExtern { Extern(V), } -pub(crate) enum ResolvedImport { - Extern(Extern), - Store(ExternVal), -} - -impl ResolvedImport { - fn initialize(self, store: &mut crate::Store, idx: ModuleInstanceAddr) -> Result { - match self { - Self::Extern(extern_) => match extern_ { - Extern::Global(global) => { - let addr = store.add_global(global.ty, global.val.into(), idx)?; - Ok(ExternVal::Global(addr)) - } - Extern::Table(table) => { - // todo: do something with the initial value - let addr = store.add_table(table.ty, idx)?; - Ok(ExternVal::Table(addr)) - } - Extern::Memory(memory) => { - let addr = store.add_mem(memory.ty, idx)?; - Ok(ExternVal::Mem(addr)) - } - Extern::Func(func) => { - let addr = store.add_func(func, idx)?; - Ok(ExternVal::Func(addr)) - } - }, - Self::Store(extern_val) => Ok(extern_val.clone()), - } - } -} - pub(crate) struct ResolvedImports { - pub(crate) globals: Vec>, - pub(crate) tables: Vec>, - pub(crate) mems: Vec>, - pub(crate) funcs: Vec>, + pub(crate) globals: Vec, + pub(crate) tables: Vec, + pub(crate) mems: Vec, + pub(crate) funcs: Vec, } impl ResolvedImports { pub(crate) fn new() -> Self { - Self { - globals: Vec::new(), - tables: Vec::new(), - mems: Vec::new(), - funcs: Vec::new(), - } - } - - pub(crate) fn globals(&self) -> &[ResolvedExtern] { - &self.globals - } - - pub(crate) fn tables(&self) -> &[ResolvedExtern] { - &self.tables - } - - pub(crate) fn mems(&self) -> &[ResolvedExtern] { - &self.mems - } - - pub(crate) fn funcs(&self) -> &[ResolvedExtern] { - &self.funcs + Self { globals: Vec::new(), tables: Vec::new(), mems: Vec::new(), funcs: Vec::new() } } } impl Imports { /// Create a new empty import set pub fn new() -> Self { - Imports { - values: BTreeMap::new(), - modules: BTreeMap::new(), - } + Imports { values: BTreeMap::new(), modules: BTreeMap::new() } } /// Link a module @@ -268,39 +192,43 @@ impl Imports { /// Define an import pub fn define(&mut self, module: &str, name: &str, value: Extern) -> Result<&mut Self> { - self.values.insert( - ExternName { - module: module.to_string(), - name: name.to_string(), - }, - value, - ); + self.values.insert(ExternName { module: module.to_string(), name: name.to_string() }, value); Ok(self) } - pub(crate) fn take(&mut self, store: &mut crate::Store, import: &Import) -> Option { - // TODO: compare types - + pub(crate) fn take( + &mut self, + store: &mut crate::Store, + import: &Import, + ) -> Option> { let name = ExternName::from(import); - if let Some(v) = self.values.remove(&name) { - return Some(ResolvedImport::Extern(v)); + log::error!("provided externs: {:?}", self.values.keys()); + if let Some(v) = self.values.get(&name) { + return Some(ResolvedExtern::Extern(v.clone())); } - - return None; - - // TODO: allow linking to other modules - // if let Some(module_addr) = self.modules.get(&name.module) { - // let Some(module) = store.get_module_instance(*module_addr) else { - // return None; + log::error!("failed to resolve import: {:?}", name); + // TODO: + // if let Some(addr) = self.modules.get(&name.module) { + // let instance = store.get_module_instance(*addr)?; + // let exports = instance.exports(); + + // let export = exports.get_untyped(&import.name)?; + // let addr = match export.kind { + // ExternalKind::Global(g) => ExternVal::Global(), // }; - // let export = module.exports().get_untyped(&name.name)?; - // }; + // return Some(ResolvedExtern::Store()); + // } - // then check if the import is defined + None } - pub(crate) fn link(mut self, store: &mut crate::Store, module: &crate::Module) -> Result { + pub(crate) fn link( + mut self, + store: &mut crate::Store, + module: &crate::Module, + idx: ModuleInstanceAddr, + ) -> Result { let mut imports = ResolvedImports::new(); for import in module.data.imports.iter() { @@ -311,28 +239,57 @@ impl Imports { }); }; - // validate import - // if export.kind != (&import.kind).into() { - // return Err(crate::Error::InvalidImportType { - // module: import.module.to_string(), - // name: import.name.to_string(), - // }); - // } - - // let val = match export.kind { - // ExternalKind::Func => ExternVal::Func(export.index), - // ExternalKind::Global => ExternVal::Global(export.index), - // ExternalKind::Table => ExternVal::Table(export.index), - // ExternalKind::Memory => ExternVal::Mem(export.index), - // }; - - // imports.0.insert( - // ExternName { - // module: import.module.to_string(), - // name: import.name.to_string(), - // }, - // ResolvedImport::Store(val), - // ); + match val { + // A link to something that needs to be added to the store + ResolvedExtern::Extern(ex) => { + // check if the kind matches + let kind = ex.kind(); + if kind != (&import.kind).into() { + return Err(crate::Error::InvalidImportType { + module: import.module.to_string(), + name: import.name.to_string(), + }); + } + + // TODO: check if the type matches + + // add it to the store and get the address + let addr = match ex { + Extern::Global(g) => store.add_global(g.ty, g.val.into(), idx)?, + Extern::Table(t) => store.add_table(t.ty, idx)?, + Extern::Memory(m) => store.add_mem(m.ty, idx)?, + Extern::Func(f) => store.add_func(f, idx)?, + }; + + // store the link + match &kind { + ExternalKind::Global => imports.globals.push(addr), + ExternalKind::Table => imports.tables.push(addr), + ExternalKind::Memory => imports.mems.push(addr), + ExternalKind::Func => imports.funcs.push(addr), + } + } + + // A link to something already in the store + ResolvedExtern::Store(val) => { + // check if the kind matches + if val.kind() != (&import.kind).into() { + return Err(crate::Error::InvalidImportType { + module: import.module.to_string(), + name: import.name.to_string(), + }); + } + + // TODO: check if the type matches + + match val { + ExternVal::Global(g) => imports.globals.push(g), + ExternVal::Table(t) => imports.tables.push(t), + ExternVal::Mem(m) => imports.mems.push(m), + ExternVal::Func(f) => imports.funcs.push(f), + } + } + } } Ok(imports) diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index b8f87d7..92db518 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -1,11 +1,12 @@ use alloc::{boxed::Box, format, string::ToString, sync::Arc, vec::Vec}; use tinywasm_types::{ - DataAddr, ElemAddr, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr, ModuleInstanceAddr, TableAddr, + DataAddr, ElemAddr, Export, ExternVal, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr, + ModuleInstanceAddr, TableAddr, }; use crate::{ func::{FromWasmValueTuple, IntoWasmValueTuple}, - Error, ExportInstance, FuncHandle, Imports, Module, Result, Store, TypedFuncHandle, + Error, FuncHandle, Imports, Module, Result, Store, TypedFuncHandle, }; /// A WebAssembly Module Instance @@ -32,7 +33,7 @@ pub(crate) struct ModuleInstanceInner { pub(crate) func_start: Option, pub(crate) imports: Box<[Import]>, - pub(crate) exports: ExportInstance, + pub(crate) exports: Box<[Export]>, } impl ModuleInstance { @@ -52,36 +53,33 @@ impl ModuleInstance { let idx = store.next_module_instance_idx(); let imports = imports.unwrap_or_default(); - let linked_imports = imports.link(store, &module)?; - let global_addrs = store.add_globals(module.data.globals.into(), idx)?; + let mut addrs = imports.link(store, &module, idx)?; + let data = module.data; - // TODO: imported functions missing - let func_addrs = store.add_funcs(module.data.funcs.into(), idx)?; + addrs.globals.extend(store.init_globals(data.globals.into(), idx)?); + addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?); + addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?); + addrs.mems.extend(store.init_mems(data.memory_types.into(), idx)?); - let table_addrs = store.add_tables(module.data.table_types.into(), idx)?; - let mem_addrs = store.add_mems(module.data.memory_types.into(), idx)?; - - // TODO: active/declared elems need to be initialized - let elem_addrs = store.add_elems(module.data.elements.into(), idx)?; - - // TODO: active data segments need to be initialized - let data_addrs = store.add_datas(module.data.data.into(), idx)?; + let elem_addrs = store.add_elems(data.elements.into(), idx)?; + let data_addrs = store.add_datas(data.data.into(), idx)?; let instance = ModuleInstanceInner { store_id: store.id(), idx, - types: module.data.func_types, - func_addrs, - table_addrs, - mem_addrs, - global_addrs, + types: data.func_types, + + func_addrs: addrs.funcs, + table_addrs: addrs.tables, + mem_addrs: addrs.mems, + global_addrs: addrs.globals, elem_addrs, data_addrs, - func_start: module.data.start_func, - imports: module.data.imports, - exports: crate::ExportInstance(module.data.exports), + func_start: data.start_func, + imports: data.imports, + exports: data.exports, }; let instance = ModuleInstance::new(instance); @@ -91,8 +89,17 @@ impl ModuleInstance { } /// Get the module's exports - pub fn exports(&self) -> &ExportInstance { - &self.0.exports + pub(crate) fn export(&self, name: &str) -> Option { + let exports = self.0.exports.iter().find(|e| e.name == name.into())?; + let kind = exports.kind.clone(); + let addr = match kind { + ExternalKind::Func => self.0.func_addrs.get(exports.index as usize)?, + ExternalKind::Table => self.0.table_addrs.get(exports.index as usize)?, + ExternalKind::Memory => self.0.mem_addrs.get(exports.index as usize)?, + ExternalKind::Global => self.0.global_addrs.get(exports.index as usize)?, + }; + + Some(ExternVal::new(kind, *addr)) } pub(crate) fn func_addrs(&self) -> &[FuncAddr] { @@ -145,28 +152,21 @@ impl ModuleInstance { return Err(Error::InvalidStore); } - let export = self - .0 - .exports - .get(name, ExternalKind::Func) - .ok_or_else(|| Error::Other(format!("Export not found: {}", name)))?; - - let func_addr = self - .0 - .func_addrs - .get(export.index as usize) - .expect("No func addr for export, this is a bug"); + let export = self.export(name).ok_or_else(|| Error::Other(format!("Export not found: {}", name)))?; + let ExternVal::Func(func_addr) = export else { + return Err(Error::Other(format!("Export is not a function: {}", name))); + }; - let func_inst = store.get_func(*func_addr as usize)?; + let func_inst = store.get_func(func_addr as usize)?; let func = func_inst.assert_wasm()?; - let ty = self.0.types[func.ty_addr as usize].clone(); + let ty = self + .0 + .types + .get(func.ty_addr as usize) + .ok_or_else(|| Error::Other(format!("Invalid function type address: {}", func.ty_addr)))? + .clone(); - Ok(FuncHandle { - addr: export.index, - module: self.clone(), - name: Some(name.to_string()), - ty, - }) + Ok(FuncHandle { addr: func_addr, module: self.clone(), name: Some(name.to_string()), ty }) } /// Get a typed exported function by name @@ -176,10 +176,7 @@ impl ModuleInstance { R: FromWasmValueTuple, { let func = self.exported_func_by_name(store, name)?; - Ok(TypedFuncHandle { - func, - marker: core::marker::PhantomData, - }) + Ok(TypedFuncHandle { func, marker: core::marker::PhantomData }) } /// Get the start function of the module @@ -198,30 +195,21 @@ impl ModuleInstance { Some(func_index) => func_index, None => { // alternatively, check for a _start function in the exports - let Some(start) = self.0.exports.get("_start", ExternalKind::Func) else { + let Some(ExternVal::Func(func_addr)) = self.export("_start") else { return Ok(None); }; - start.index + func_addr } }; - let func_addr = self - .0 - .func_addrs - .get(func_index as usize) - .expect("No func addr for start func, this is a bug"); + let func_addr = self.0.func_addrs.get(func_index as usize).expect("No func addr for start func, this is a bug"); let func_inst = store.get_func(*func_addr as usize)?; let func = func_inst.assert_wasm()?; let ty = self.0.types[func.ty_addr as usize].clone(); - Ok(Some(FuncHandle { - module: self.clone(), - addr: *func_addr, - ty, - name: None, - })) + Ok(Some(FuncHandle { module: self.clone(), addr: *func_addr, ty, name: None })) } /// Invoke the start function of the module diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs index 0c1863f..64d34df 100644 --- a/crates/tinywasm/src/lib.rs +++ b/crates/tinywasm/src/lib.rs @@ -2,10 +2,7 @@ #![forbid(unsafe_code)] #![doc(test( no_crate_inject, - attr( - deny(warnings, rust_2018_idioms), - allow(dead_code, unused_assignments, unused_variables) - ) + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_assignments, unused_variables)) ))] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] #![cfg_attr(nightly, feature(error_in_core))] @@ -89,9 +86,6 @@ pub use module::Module; mod instance; pub use instance::ModuleInstance; -mod export; -pub use export::ExportInstance; - mod func; pub use func::{FuncHandle, TypedFuncHandle}; diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 5e191cc..62f17e7 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -16,7 +16,6 @@ use traits::*; impl DefaultRuntime { pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack, module: ModuleInstance) -> Result<()> { - log::debug!("exports: {:?}", module.exports()); log::debug!("func_addrs: {:?}", module.func_addrs()); log::debug!("func_ty_addrs: {:?}", module.func_ty_addrs().len()); log::debug!("store funcs: {:?}", store.data.funcs.len()); @@ -162,11 +161,9 @@ fn exec_one( let func_ty = module.func_ty(func.ty_addr); if func_ty != call_ty { - return Err(Trap::IndirectCallTypeMismatch { - actual: func_ty.clone(), - expected: call_ty.clone(), - } - .into()); + return Err( + Trap::IndirectCallTypeMismatch { actual: func_ty.clone(), expected: call_ty.clone() }.into() + ); } let params = stack.values.pop_n(func_ty.params.len())?; @@ -569,10 +566,7 @@ fn exec_one( i => { log::error!("unimplemented instruction: {:?}", i); - return Err(Error::UnsupportedFeature(alloc::format!( - "unimplemented instruction: {:?}", - i - ))); + return Err(Error::UnsupportedFeature(alloc::format!("unimplemented instruction: {:?}", i))); } }; diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 9b2f711..426ca78 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -7,7 +7,7 @@ use core::{ use alloc::{format, rc::Rc, string::ToString, vec, vec::Vec}; use tinywasm_types::{ - Addr, Data, DataAddr, ElemAddr, Element, ElementKind, FuncAddr, Global, GlobalType, Import, MemAddr, MemoryArch, + Addr, Data, DataAddr, ElemAddr, Element, ElementKind, FuncAddr, Global, GlobalType, MemAddr, MemoryArch, MemoryType, ModuleInstanceAddr, TableAddr, TableType, WasmFunction, }; @@ -114,7 +114,7 @@ impl Store { } /// Add functions to the store, returning their addresses in the store - pub(crate) fn add_funcs(&mut self, funcs: Vec, idx: ModuleInstanceAddr) -> Result> { + pub(crate) fn init_funcs(&mut self, funcs: Vec, idx: ModuleInstanceAddr) -> Result> { let func_count = self.data.funcs.len(); let mut func_addrs = Vec::with_capacity(func_count); for func in funcs.into_iter() { @@ -124,7 +124,7 @@ impl Store { } /// Add tables to the store, returning their addresses in the store - pub(crate) fn add_tables(&mut self, tables: Vec, idx: ModuleInstanceAddr) -> Result> { + pub(crate) fn init_tables(&mut self, tables: Vec, idx: ModuleInstanceAddr) -> Result> { let table_count = self.data.tables.len(); let mut table_addrs = Vec::with_capacity(table_count); for (i, table) in tables.into_iter().enumerate() { @@ -134,7 +134,7 @@ impl Store { } /// Add memories to the store, returning their addresses in the store - pub(crate) fn add_mems(&mut self, mems: Vec, idx: ModuleInstanceAddr) -> Result> { + pub(crate) fn init_mems(&mut self, mems: Vec, idx: ModuleInstanceAddr) -> Result> { let mem_count = self.data.mems.len(); let mut mem_addrs = Vec::with_capacity(mem_count); for (i, mem) in mems.into_iter().enumerate() { @@ -144,7 +144,7 @@ impl Store { } /// Add globals to the store, returning their addresses in the store - pub(crate) fn add_globals(&mut self, globals: Vec, idx: ModuleInstanceAddr) -> Result> { + pub(crate) fn init_globals(&mut self, globals: Vec, idx: ModuleInstanceAddr) -> Result> { let global_count = self.data.globals.len(); let mut global_addrs = Vec::with_capacity(global_count); // then add the module globals @@ -156,16 +156,12 @@ impl Store { } pub(crate) fn add_global(&mut self, ty: GlobalType, value: RawWasmValue, idx: ModuleInstanceAddr) -> Result { - self.data - .globals - .push(Rc::new(RefCell::new(GlobalInstance::new(ty, value, idx)))); + self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new(ty, value, idx)))); Ok(self.data.globals.len() as Addr - 1) } pub(crate) fn add_table(&mut self, table: TableType, idx: ModuleInstanceAddr) -> Result { - self.data - .tables - .push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); + self.data.tables.push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); Ok(self.data.tables.len() as TableAddr - 1) } @@ -173,9 +169,7 @@ impl Store { if let MemoryArch::I64 = mem.arch { return Err(Error::UnsupportedFeature("64-bit memories".to_string())); } - self.data - .mems - .push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); + self.data.mems.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); Ok(self.data.mems.len() as MemAddr - 1) } @@ -203,6 +197,7 @@ impl Store { Ok(self.data.funcs.len() as FuncAddr - 1) } + /// Evaluate a constant expression, only supporting i32 globals and i32.const pub(crate) fn eval_i32_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { use tinywasm_types::ConstInstruction::*; let val = match const_instr { @@ -218,6 +213,7 @@ impl Store { Ok(val) } + /// Evaluate a constant expression pub(crate) fn eval_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { use tinywasm_types::ConstInstruction::*; let val = match const_instr { @@ -300,9 +296,7 @@ impl Store { Active { mem: mem_addr, offset } => { // a. Assert: memidx == 0 if mem_addr != 0 { - return Err(Error::UnsupportedFeature( - "data segments for non-zero memories".to_string(), - )); + return Err(Error::UnsupportedFeature("data segments for non-zero memories".to_string())); } let offset = self.eval_i32_const(&offset)?; @@ -328,33 +322,21 @@ impl Store { /// Get the function at the actual index in the store pub(crate) fn get_func(&self, addr: usize) -> Result<&Rc> { - self.data - .funcs - .get(addr) - .ok_or_else(|| Error::Other(format!("function {} not found", addr))) + self.data.funcs.get(addr).ok_or_else(|| Error::Other(format!("function {} not found", addr))) } /// Get the memory at the actual index in the store pub(crate) fn get_mem(&self, addr: usize) -> Result<&Rc>> { - self.data - .mems - .get(addr) - .ok_or_else(|| Error::Other(format!("memory {} not found", addr))) + self.data.mems.get(addr).ok_or_else(|| Error::Other(format!("memory {} not found", addr))) } /// Get the table at the actual index in the store pub(crate) fn get_table(&self, addr: usize) -> Result<&Rc>> { - self.data - .tables - .get(addr) - .ok_or_else(|| Error::Other(format!("table {} not found", addr))) + self.data.tables.get(addr).ok_or_else(|| Error::Other(format!("table {} not found", addr))) } pub(crate) fn get_elem(&self, addr: usize) -> Result<&ElemInstance> { - self.data - .elems - .get(addr) - .ok_or_else(|| Error::Other(format!("element {} not found", addr))) + self.data.elems.get(addr).ok_or_else(|| Error::Other(format!("element {} not found", addr))) } /// Get the global at the actual index in the store @@ -413,18 +395,11 @@ pub(crate) struct TableInstance { impl TableInstance { pub(crate) fn new(kind: TableType, owner: ModuleInstanceAddr) -> Self { - Self { - elements: vec![0; kind.size_initial as usize], - kind, - owner, - } + Self { elements: vec![0; kind.size_initial as usize], kind, owner } } pub(crate) fn get(&self, addr: usize) -> Result { - self.elements - .get(addr) - .copied() - .ok_or_else(|| Trap::UndefinedElement { index: addr }.into()) + self.elements.get(addr).copied().ok_or_else(|| Trap::UndefinedElement { index: addr }.into()) } pub(crate) fn set(&mut self, addr: usize, value: Addr) -> Result<()> { @@ -442,20 +417,11 @@ impl TableInstance { pub(crate) fn init(&mut self, offset: i32, init: &[Addr]) -> Result<()> { let offset = offset as usize; let end = offset.checked_add(init.len()).ok_or_else(|| { - Error::Trap(crate::Trap::TableOutOfBounds { - offset, - len: init.len(), - max: self.elements.len(), - }) + Error::Trap(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() }) })?; if end > self.elements.len() || end < offset { - return Err(crate::Trap::TableOutOfBounds { - offset, - len: init.len(), - max: self.elements.len(), - } - .into()); + return Err(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() }.into()); } self.elements[offset..end].copy_from_slice(init); @@ -493,11 +459,7 @@ impl MemoryInstance { pub(crate) fn store(&mut self, addr: usize, _align: usize, data: &[u8]) -> Result<()> { let end = addr.checked_add(data.len()).ok_or_else(|| { - Error::Trap(crate::Trap::MemoryOutOfBounds { - offset: addr, - len: data.len(), - max: self.data.len(), - }) + Error::Trap(crate::Trap::MemoryOutOfBounds { offset: addr, len: data.len(), max: self.data.len() }) })?; if end > self.data.len() || end < addr { @@ -518,20 +480,12 @@ impl MemoryInstance { } pub(crate) fn load(&self, addr: usize, _align: usize, len: usize) -> Result<&[u8]> { - let end = addr.checked_add(len).ok_or_else(|| { - Error::Trap(crate::Trap::MemoryOutOfBounds { - offset: addr, - len, - max: self.max_pages(), - }) - })?; + let end = addr + .checked_add(len) + .ok_or_else(|| Error::Trap(crate::Trap::MemoryOutOfBounds { offset: addr, len, max: self.max_pages() }))?; if end > self.data.len() { - return Err(Error::Trap(crate::Trap::MemoryOutOfBounds { - offset: addr, - len, - max: self.data.len(), - })); + return Err(Error::Trap(crate::Trap::MemoryOutOfBounds { offset: addr, len, max: self.data.len() })); } // WebAssembly doesn't require alignment for loads diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index e175639..a1eaf8c 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19816,412,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":159,"failed":11},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":48,"failed":13},{"name":"elem.wast","passed":76,"failed":23},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":32,"failed":4},{"name":"global.wast","passed":96,"failed":14},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":52,"failed":131},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":20,"failed":112},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":143,"failed":5},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":17,"failed":3},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19691,537,[{"name":"address.wast","passed":223,"failed":37},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":151,"failed":19},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":54,"failed":7},{"name":"elem.wast","passed":61,"failed":38},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":80,"failed":10},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":169,"failed":3},{"name":"func_ptrs.wast","passed":19,"failed":17},{"name":"global.wast","passed":106,"failed":4},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":65,"failed":118},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":89,"failed":7},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":143,"failed":5},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":14,"failed":6},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index ac7f854..4d3c59a 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -2,10 +2,7 @@ #![forbid(unsafe_code)] #![doc(test( no_crate_inject, - attr( - deny(warnings, rust_2018_idioms), - allow(dead_code, unused_assignments, unused_variables) - ) + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_assignments, unused_variables)) ))] #![warn(missing_debug_implementations, rust_2018_idioms, unreachable_pub)] @@ -314,6 +311,26 @@ pub enum ExternVal { Global(GlobalAddr), } +impl ExternVal { + pub fn kind(&self) -> ExternalKind { + match self { + Self::Func(_) => ExternalKind::Func, + Self::Table(_) => ExternalKind::Table, + Self::Mem(_) => ExternalKind::Memory, + Self::Global(_) => ExternalKind::Global, + } + } + + pub fn new(kind: ExternalKind, addr: Addr) -> Self { + match kind { + ExternalKind::Func => Self::Func(addr), + ExternalKind::Table => Self::Table(addr), + ExternalKind::Memory => Self::Mem(addr), + ExternalKind::Global => Self::Global(addr), + } + } +} + /// The type of a WebAssembly Function. /// /// See @@ -326,10 +343,7 @@ pub struct FuncType { impl FuncType { /// Get the number of parameters of a function type. pub fn empty() -> Self { - Self { - params: Box::new([]), - results: Box::new([]), - } + Self { params: Box::new([]), results: Box::new([]) } } } @@ -372,19 +386,11 @@ pub struct TableType { impl TableType { pub fn empty() -> Self { - Self { - element_type: ValType::FuncRef, - size_initial: 0, - size_max: None, - } + Self { element_type: ValType::FuncRef, size_initial: 0, size_max: None } } pub fn new(element_type: ValType, size_initial: u32, size_max: Option) -> Self { - Self { - element_type, - size_initial, - size_max, - } + Self { element_type, size_initial, size_max } } } @@ -400,11 +406,7 @@ pub struct MemoryType { impl MemoryType { pub fn new_32(page_count_initial: u64, page_count_max: Option) -> Self { - Self { - arch: MemoryArch::I32, - page_count_initial, - page_count_max, - } + Self { arch: MemoryArch::I32, page_count_initial, page_count_max } } // pub fn new_64(page_count_initial: u64, page_count_max: Option) -> Self { diff --git a/rustfmt.toml b/rustfmt.toml index 94ac875..589b2d2 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1 +1,2 @@ max_width=120 +use_small_heuristics="Max" From 49a4bf2a3a40f56a86928a2847e32b21e800d263 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 01:05:35 +0100 Subject: [PATCH 18/52] host function calls, fix call isolation issues Signed-off-by: Henry Gressmann --- crates/tinywasm/src/func.rs | 21 +- crates/tinywasm/src/imports.rs | 12 +- crates/tinywasm/src/instance.rs | 36 ++-- .../tinywasm/src/runtime/executor/macros.rs | 7 +- crates/tinywasm/src/runtime/executor/mod.rs | 29 ++- .../tinywasm/src/runtime/stack/value_stack.rs | 31 ++- crates/tinywasm/src/store.rs | 201 ++++++++++-------- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 6 +- 9 files changed, 202 insertions(+), 143 deletions(-) diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 74043a9..0a65e02 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -52,7 +52,13 @@ impl FuncHandle { } } - let wasm_func = &func_inst.assert_wasm()?; + let wasm_func = match &func_inst.func { + crate::Function::Host(h) => { + let func = h.func.clone(); + return (func)(store, params); + } + crate::Function::Wasm(ref f) => f, + }; // 6. Let f be the dummy frame debug!("locals: {:?}", wasm_func.locals); @@ -76,11 +82,7 @@ impl FuncHandle { let res = stack.values.last_n(result_m)?; // The values are returned as the results of the invocation. - Ok(res - .iter() - .zip(func_ty.results.iter()) - .map(|(v, ty)| v.attach_type(*ty)) - .collect()) + Ok(res.iter().zip(func_ty.results.iter()).map(|(v, ty)| v.attach_type(*ty)).collect()) } } @@ -184,11 +186,8 @@ macro_rules! impl_from_wasm_value_tuple_single { fn from_wasm_value_tuple(values: Vec) -> Result { #[allow(unused_variables, unused_mut)] let mut iter = values.into_iter(); - Ok($T::try_from( - iter.next() - .ok_or(Error::Other("Not enough values in WasmValue vector".to_string()))?, - ) - .map_err(|_| Error::Other("Could not convert WasmValue to expected type".to_string()))?) + Ok($T::try_from(iter.next().ok_or(Error::Other("Not enough values in WasmValue vector".to_string()))?) + .map_err(|_| Error::Other("Could not convert WasmValue to expected type".to_string()))?) } } }; diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index f89ba64..e17f866 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -12,7 +12,7 @@ use alloc::{ }; use tinywasm_types::{ Addr, Export, ExternVal, ExternalKind, FuncAddr, GlobalAddr, GlobalType, Import, MemAddr, MemoryType, - ModuleInstanceAddr, TableAddr, TableType, WasmFunction, WasmValue, + ModuleInstanceAddr, TableAddr, TableType, TypeAddr, WasmFunction, WasmValue, }; /// The internal representation of a function @@ -25,6 +25,16 @@ pub enum Function { Wasm(WasmFunction), } +impl Function { + /// Get the function's type + pub fn ty(&self, module: &crate::ModuleInstance) -> tinywasm_types::FuncType { + match self { + Self::Host(f) => f.ty.clone(), + Self::Wasm(f) => module.func_ty(f.ty_addr).clone(), + } + } +} + /// A host function #[derive(Clone)] pub struct HostFunction { diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 92db518..9ad1cfd 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -59,10 +59,17 @@ impl ModuleInstance { addrs.globals.extend(store.init_globals(data.globals.into(), idx)?); addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?); addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?); + + log::info!("init_mems: {:?}", addrs.mems); addrs.mems.extend(store.init_mems(data.memory_types.into(), idx)?); + log::info!("init_mems2: {:?}", addrs.mems); + log::info!("init_mems g: {:?}", store.data.mems.len()); + + let elem_addrs = store.init_elems(&addrs.tables, data.elements.into(), idx)?; + log::info!("init_elems: {:?}", addrs.mems); - let elem_addrs = store.add_elems(data.elements.into(), idx)?; - let data_addrs = store.add_datas(data.data.into(), idx)?; + let data_addrs = store.init_datas(&addrs.mems, data.data.into(), idx)?; + log::info!("init_datas: {:?}", addrs.mems); let instance = ModuleInstanceInner { store_id: store.id(), @@ -119,26 +126,22 @@ impl ModuleInstance { } pub(crate) fn func_ty(&self, addr: FuncAddr) -> &FuncType { - &self.0.types[addr as usize] + &self.0.types.get(addr as usize).expect("No func type for func, this is a bug") } // resolve a function address to the global store address pub(crate) fn resolve_func_addr(&self, addr: FuncAddr) -> FuncAddr { - self.0.func_addrs[addr as usize] + *self.0.func_addrs.get(addr as usize).expect("No func addr for func, this is a bug") } // resolve a table address to the global store address pub(crate) fn resolve_table_addr(&self, addr: TableAddr) -> TableAddr { - self.0.table_addrs[addr as usize] - } - - pub(crate) fn resolve_elem_addr(&self, addr: ElemAddr) -> ElemAddr { - self.0.elem_addrs[addr as usize] + *self.0.table_addrs.get(addr as usize).expect("No table addr for table, this is a bug") } // resolve a memory address to the global store address pub(crate) fn resolve_mem_addr(&self, addr: MemAddr) -> MemAddr { - self.0.mem_addrs[addr as usize] + *self.0.mem_addrs.get(addr as usize).expect("No mem addr for mem, this is a bug") } // resolve a global address to the global store address @@ -158,15 +161,9 @@ impl ModuleInstance { }; let func_inst = store.get_func(func_addr as usize)?; - let func = func_inst.assert_wasm()?; - let ty = self - .0 - .types - .get(func.ty_addr as usize) - .ok_or_else(|| Error::Other(format!("Invalid function type address: {}", func.ty_addr)))? - .clone(); + let ty = func_inst.func.ty(&self); - Ok(FuncHandle { addr: func_addr, module: self.clone(), name: Some(name.to_string()), ty }) + Ok(FuncHandle { addr: func_addr, module: self.clone(), name: Some(name.to_string()), ty: ty.clone() }) } /// Get a typed exported function by name @@ -206,8 +203,7 @@ impl ModuleInstance { let func_addr = self.0.func_addrs.get(func_index as usize).expect("No func addr for start func, this is a bug"); let func_inst = store.get_func(*func_addr as usize)?; - let func = func_inst.assert_wasm()?; - let ty = self.0.types[func.ty_addr as usize].clone(); + let ty = func_inst.func.ty(&self); Ok(Some(FuncHandle { module: self.clone(), addr: *func_addr, ty, name: None })) } diff --git a/crates/tinywasm/src/runtime/executor/macros.rs b/crates/tinywasm/src/runtime/executor/macros.rs index c1bb50f..5b20851 100644 --- a/crates/tinywasm/src/runtime/executor/macros.rs +++ b/crates/tinywasm/src/runtime/executor/macros.rs @@ -63,8 +63,7 @@ macro_rules! mem_store { let val = val as $store_type; let val = val.to_le_bytes(); - mem.borrow_mut() - .store(($arg.offset + addr) as usize, $arg.align as usize, &val)?; + mem.borrow_mut().store(($arg.offset + addr) as usize, $arg.align as usize, &val)?; }}; } @@ -225,9 +224,7 @@ macro_rules! checked_int_arithmetic { return Err(Error::Trap(crate::Trap::DivisionByZero)); } - let result = a_casted - .$op(b_casted) - .ok_or_else(|| Error::Trap(crate::Trap::IntegerOverflow))?; + let result = a_casted.$op(b_casted).ok_or_else(|| Error::Trap(crate::Trap::IntegerOverflow))?; // Cast back to original type if different $stack.values.push((result as $from).into()); diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 62f17e7..1072577 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -25,7 +25,7 @@ impl DefaultRuntime { // The function to execute, gets updated from ExecResult::Call let mut func_inst = store.get_func(cf.func_ptr)?.clone(); - let mut wasm_func = func_inst.assert_wasm()?; + let mut wasm_func = func_inst.assert_wasm().expect("exec expected wasm function"); let mut instrs = &wasm_func.instructions; // TODO: we might be able to index into the instructions directly @@ -36,7 +36,7 @@ impl DefaultRuntime { ExecResult::Call => { cf = stack.call_stack.pop()?; func_inst = store.get_func(cf.func_ptr)?.clone(); - wasm_func = func_inst.assert_wasm()?; + wasm_func = func_inst.assert_wasm().expect("call expected wasm function"); instrs = &wasm_func.instructions; continue; } @@ -128,14 +128,24 @@ fn exec_one( // prepare the call frame let func_idx = module.resolve_func_addr(*v); let func_inst = store.get_func(func_idx as usize)?; - let func = func_inst.assert_wasm()?; + let func = match &func_inst.func { + crate::Function::Wasm(ref f) => f, + crate::Function::Host(host_func) => { + let func = host_func.func.clone(); + let params = stack.values.pop_params(&host_func.ty.params)?; + let res = (func)(store, ¶ms)?; + stack.values.extend_from_typed(&res); + return Ok(ExecResult::Ok); + } + }; + let func_ty = module.func_ty(func.ty_addr); debug!("params: {:?}", func_ty.params); debug!("stack: {:?}", stack.values); let params = stack.values.pop_n(func_ty.params.len())?; - let call_frame = CallFrame::new_raw(*v as usize, ¶ms, func.locals.to_vec()); + let call_frame = CallFrame::new_raw(func_idx as usize, ¶ms, func.locals.to_vec()); // push the call frame cf.instr_ptr += 1; // skip the call instruction @@ -157,7 +167,16 @@ fn exec_one( // prepare the call frame let func_inst = store.get_func(func_addr as usize)?; - let func = func_inst.assert_wasm()?; + let func = match &func_inst.func { + crate::Function::Wasm(ref f) => f, + crate::Function::Host(host_func) => { + let func = host_func.func.clone(); + let params = stack.values.pop_params(&host_func.ty.params)?; + let res = (func)(store, ¶ms)?; + stack.values.extend_from_typed(&res); + return Ok(ExecResult::Ok); + } + }; let func_ty = module.func_ty(func.ty_addr); if func_ty != call_ty { diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index 10054bc..1021289 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -2,6 +2,7 @@ use core::ops::Range; use crate::{runtime::RawWasmValue, Error, Result}; use alloc::vec::Vec; +use tinywasm_types::{ValType, WasmValue}; // minimum stack size pub(crate) const STACK_SIZE: usize = 1024; @@ -16,10 +17,7 @@ pub(crate) struct ValueStack { impl Default for ValueStack { fn default() -> Self { - Self { - stack: Vec::with_capacity(STACK_SIZE), - top: 0, - } + Self { stack: Vec::with_capacity(STACK_SIZE), top: 0 } } } @@ -30,6 +28,12 @@ impl ValueStack { self.stack.extend_from_within(range); } + #[inline] + pub(crate) fn extend_from_typed(&mut self, values: &[WasmValue]) { + self.top += values.len(); + self.stack.extend(values.iter().map(|v| RawWasmValue::from(*v))); + } + #[inline] pub(crate) fn len(&self) -> usize { assert!(self.top <= self.stack.len()); @@ -38,10 +42,7 @@ impl ValueStack { pub(crate) fn truncate_keep(&mut self, n: usize, end_keep: usize) { let total_to_keep = n + end_keep; - assert!( - self.top >= total_to_keep, - "Total to keep should be less than or equal to self.top" - ); + assert!(self.top >= total_to_keep, "Total to keep should be less than or equal to self.top"); let current_size = self.stack.len(); if current_size <= total_to_keep { @@ -79,9 +80,19 @@ impl ValueStack { self.stack.pop().ok_or(Error::StackUnderflow) } + #[inline] + pub(crate) fn pop_params(&mut self, types: &[ValType]) -> Result> { + let n = types.len(); + if self.top < n { + return Err(Error::StackUnderflow); + } + self.top -= n; + let res = self.stack.drain(self.top..).rev().map(|v| v.attach_type(types[n - 1])).collect(); + Ok(res) + } + pub(crate) fn break_to(&mut self, new_stack_size: usize, result_count: usize) { - self.stack - .copy_within((self.top - result_count)..self.top, new_stack_size); + self.stack.copy_within((self.top - result_count)..self.top, new_stack_size); self.top = new_stack_size + result_count; self.stack.truncate(self.top); } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 426ca78..e7fc7b1 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -106,8 +106,8 @@ impl Store { self.module_instance_count as ModuleInstanceAddr } - /// Initialize the store with global state from the given module pub(crate) fn add_instance(&mut self, instance: ModuleInstance) -> Result<()> { + assert!(instance.id() == self.module_instance_count as ModuleInstanceAddr); self.module_instances.push(instance); self.module_instance_count += 1; Ok(()) @@ -117,8 +117,9 @@ impl Store { pub(crate) fn init_funcs(&mut self, funcs: Vec, idx: ModuleInstanceAddr) -> Result> { let func_count = self.data.funcs.len(); let mut func_addrs = Vec::with_capacity(func_count); - for func in funcs.into_iter() { - func_addrs.push(self.add_func(Function::Wasm(func), idx)?); + for (i, func) in funcs.into_iter().enumerate() { + self.data.funcs.push(Rc::new(FunctionInstance { func: Function::Wasm(func), owner: idx })); + func_addrs.push((i + func_count) as FuncAddr); } Ok(func_addrs) } @@ -128,7 +129,8 @@ impl Store { let table_count = self.data.tables.len(); let mut table_addrs = Vec::with_capacity(table_count); for (i, table) in tables.into_iter().enumerate() { - table_addrs.push(self.add_table(table, idx)?); + self.data.tables.push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); + table_addrs.push((i + table_count) as TableAddr); } Ok(table_addrs) } @@ -138,7 +140,13 @@ impl Store { let mem_count = self.data.mems.len(); let mut mem_addrs = Vec::with_capacity(mem_count); for (i, mem) in mems.into_iter().enumerate() { - mem_addrs.push(self.add_mem(mem, idx)?); + if let MemoryArch::I64 = mem.arch { + return Err(Error::UnsupportedFeature("64-bit memories".to_string())); + } + log::info!("adding memory: {:?}", mem); + self.data.mems.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); + + mem_addrs.push((i + mem_count) as MemAddr); } Ok(mem_addrs) } @@ -155,87 +163,14 @@ impl Store { Ok(global_addrs) } - pub(crate) fn add_global(&mut self, ty: GlobalType, value: RawWasmValue, idx: ModuleInstanceAddr) -> Result { - self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new(ty, value, idx)))); - Ok(self.data.globals.len() as Addr - 1) - } - - pub(crate) fn add_table(&mut self, table: TableType, idx: ModuleInstanceAddr) -> Result { - self.data.tables.push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); - Ok(self.data.tables.len() as TableAddr - 1) - } - - pub(crate) fn add_mem(&mut self, mem: MemoryType, idx: ModuleInstanceAddr) -> Result { - if let MemoryArch::I64 = mem.arch { - return Err(Error::UnsupportedFeature("64-bit memories".to_string())); - } - self.data.mems.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); - Ok(self.data.mems.len() as MemAddr - 1) - } - - pub(crate) fn add_elem(&mut self, elem: Element, idx: ModuleInstanceAddr) -> Result { - let init = elem - .items - .iter() - .map(|item| { - item.addr() - .ok_or_else(|| Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item))) - }) - .collect::>>()?; - - self.data.elems.push(ElemInstance::new(elem.kind, idx, Some(init))); - Ok(self.data.elems.len() as ElemAddr - 1) - } - - pub(crate) fn add_data(&mut self, data: Data, idx: ModuleInstanceAddr) -> Result { - self.data.datas.push(DataInstance::new(data.data.to_vec(), idx)); - Ok(self.data.datas.len() as DataAddr - 1) - } - - pub(crate) fn add_func(&mut self, func: Function, idx: ModuleInstanceAddr) -> Result { - self.data.funcs.push(Rc::new(FunctionInstance { func, owner: idx })); - Ok(self.data.funcs.len() as FuncAddr - 1) - } - - /// Evaluate a constant expression, only supporting i32 globals and i32.const - pub(crate) fn eval_i32_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { - use tinywasm_types::ConstInstruction::*; - let val = match const_instr { - I32Const(i) => *i, - GlobalGet(addr) => { - let addr = *addr as usize; - let global = self.data.globals[addr].clone(); - let val = global.borrow().value; - i32::from(val) - } - _ => return Err(Error::Other("expected i32".to_string())), - }; - Ok(val) - } - - /// Evaluate a constant expression - pub(crate) fn eval_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { - use tinywasm_types::ConstInstruction::*; - let val = match const_instr { - F32Const(f) => RawWasmValue::from(*f), - F64Const(f) => RawWasmValue::from(*f), - I32Const(i) => RawWasmValue::from(*i), - I64Const(i) => RawWasmValue::from(*i), - GlobalGet(addr) => { - let addr = *addr as usize; - let global = self.data.globals[addr].clone(); - let val = global.borrow().value; - val - } - RefNull(v) => v.default_value().into(), - RefFunc(idx) => RawWasmValue::from(*idx as i64), - }; - Ok(val) - } - /// Add elements to the store, returning their addresses in the store /// Should be called after the tables have been added - pub(crate) fn add_elems(&mut self, elems: Vec, idx: ModuleInstanceAddr) -> Result> { + pub(crate) fn init_elems( + &mut self, + table_addrs: &[TableAddr], + elems: Vec, + idx: ModuleInstanceAddr, + ) -> Result> { let elem_count = self.data.elems.len(); let mut elem_addrs = Vec::with_capacity(elem_count); for (i, elem) in elems.into_iter().enumerate() { @@ -262,13 +197,17 @@ impl Store { // this one is active, so we need to initialize it (essentially a `table.init` instruction) ElementKind::Active { offset, table } => { let offset = self.eval_i32_const(&offset)?; + let table_addr = table_addrs + .get(table as usize) + .copied() + .ok_or_else(|| Error::Other(format!("table {} not found for element {}", table, i)))?; // a. Let n be the length of the vector elem[i].init // b. Execute the instruction sequence einstrs // c. Execute the instruction i32.const 0 // d. Execute the instruction i32.const n // e. Execute the instruction table.init tableidx i - if let Some(table) = self.data.tables.get_mut(table as usize) { + if let Some(table) = self.data.tables.get_mut(table_addr as usize) { table.borrow_mut().init(offset, &init)?; } else { log::error!("table {} not found", table); @@ -287,7 +226,12 @@ impl Store { } /// Add data to the store, returning their addresses in the store - pub(crate) fn add_datas(&mut self, datas: Vec, idx: ModuleInstanceAddr) -> Result> { + pub(crate) fn init_datas( + &mut self, + mem_addrs: &[MemAddr], + datas: Vec, + idx: ModuleInstanceAddr, + ) -> Result> { let data_count = self.data.datas.len(); let mut data_addrs = Vec::with_capacity(data_count); for (i, data) in datas.into_iter().enumerate() { @@ -299,6 +243,11 @@ impl Store { return Err(Error::UnsupportedFeature("data segments for non-zero memories".to_string())); } + let mem_addr = mem_addrs + .get(mem_addr as usize) + .copied() + .ok_or_else(|| Error::Other(format!("memory {} not found for data segment {}", mem_addr, i)))?; + let offset = self.eval_i32_const(&offset)?; let mem = @@ -308,7 +257,7 @@ impl Store { mem.borrow_mut().store(offset as usize, 0, &data.data)?; - // drop the date + // drop the data continue; } Passive => {} @@ -320,6 +269,84 @@ impl Store { Ok(data_addrs) } + pub(crate) fn add_global(&mut self, ty: GlobalType, value: RawWasmValue, idx: ModuleInstanceAddr) -> Result { + self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new(ty, value, idx)))); + Ok(self.data.globals.len() as Addr - 1) + } + + pub(crate) fn add_table(&mut self, table: TableType, idx: ModuleInstanceAddr) -> Result { + self.data.tables.push(Rc::new(RefCell::new(TableInstance::new(table, idx)))); + Ok(self.data.tables.len() as TableAddr - 1) + } + + pub(crate) fn add_mem(&mut self, mem: MemoryType, idx: ModuleInstanceAddr) -> Result { + if let MemoryArch::I64 = mem.arch { + return Err(Error::UnsupportedFeature("64-bit memories".to_string())); + } + self.data.mems.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); + Ok(self.data.mems.len() as MemAddr - 1) + } + + pub(crate) fn add_elem(&mut self, elem: Element, idx: ModuleInstanceAddr) -> Result { + let init = elem + .items + .iter() + .map(|item| { + item.addr() + .ok_or_else(|| Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item))) + }) + .collect::>>()?; + + self.data.elems.push(ElemInstance::new(elem.kind, idx, Some(init))); + Ok(self.data.elems.len() as ElemAddr - 1) + } + + pub(crate) fn add_data(&mut self, data: Data, idx: ModuleInstanceAddr) -> Result { + self.data.datas.push(DataInstance::new(data.data.to_vec(), idx)); + Ok(self.data.datas.len() as DataAddr - 1) + } + + pub(crate) fn add_func(&mut self, func: Function, idx: ModuleInstanceAddr) -> Result { + self.data.funcs.push(Rc::new(FunctionInstance { func, owner: idx })); + Ok(self.data.funcs.len() as FuncAddr - 1) + } + + /// Evaluate a constant expression, only supporting i32 globals and i32.const + pub(crate) fn eval_i32_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { + use tinywasm_types::ConstInstruction::*; + let val = match const_instr { + I32Const(i) => *i, + GlobalGet(addr) => { + let addr = *addr as usize; + let global = self.data.globals[addr].clone(); + let val = global.borrow().value; + i32::from(val) + } + _ => return Err(Error::Other("expected i32".to_string())), + }; + Ok(val) + } + + /// Evaluate a constant expression + pub(crate) fn eval_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { + use tinywasm_types::ConstInstruction::*; + let val = match const_instr { + F32Const(f) => RawWasmValue::from(*f), + F64Const(f) => RawWasmValue::from(*f), + I32Const(i) => RawWasmValue::from(*i), + I64Const(i) => RawWasmValue::from(*i), + GlobalGet(addr) => { + let addr = *addr as usize; + let global = self.data.globals[addr].clone(); + let val = global.borrow().value; + val + } + RefNull(v) => v.default_value().into(), + RefFunc(idx) => RawWasmValue::from(*idx as i64), + }; + Ok(val) + } + /// Get the function at the actual index in the store pub(crate) fn get_func(&self, addr: usize) -> Result<&Rc> { self.data.funcs.get(addr).ok_or_else(|| Error::Other(format!("function {} not found", addr))) diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index a1eaf8c..824bf55 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19691,537,[{"name":"address.wast","passed":223,"failed":37},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":151,"failed":19},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":54,"failed":7},{"name":"elem.wast","passed":61,"failed":38},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":80,"failed":10},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":169,"failed":3},{"name":"func_ptrs.wast","passed":19,"failed":17},{"name":"global.wast","passed":106,"failed":4},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":65,"failed":118},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":89,"failed":7},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":143,"failed":5},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":14,"failed":6},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19831,397,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":155,"failed":15},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":69,"failed":30},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":170,"failed":2},{"name":"func_ptrs.wast","passed":20,"failed":16},{"name":"global.wast","passed":106,"failed":4},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":70,"failed":113},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":92,"failed":4},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":143,"failed":5},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 5e3f57b..1f8316a 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (19775) +v0.3.0-alpha.0 (19831) - + - + From c0dd4bc48f703b46f6e0f683c10c015c92f46bba Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 01:14:27 +0100 Subject: [PATCH 19/52] cleanup Signed-off-by: Henry Gressmann --- crates/tinywasm/src/func.rs | 4 +- crates/tinywasm/src/imports.rs | 14 +++--- crates/tinywasm/src/instance.rs | 6 +-- crates/tinywasm/src/store.rs | 76 +++++++++++---------------------- crates/types/src/lib.rs | 2 +- 5 files changed, 40 insertions(+), 62 deletions(-) diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 0a65e02..8546b9f 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -186,8 +186,8 @@ macro_rules! impl_from_wasm_value_tuple_single { fn from_wasm_value_tuple(values: Vec) -> Result { #[allow(unused_variables, unused_mut)] let mut iter = values.into_iter(); - Ok($T::try_from(iter.next().ok_or(Error::Other("Not enough values in WasmValue vector".to_string()))?) - .map_err(|_| Error::Other("Could not convert WasmValue to expected type".to_string()))?) + $T::try_from(iter.next().ok_or(Error::Other("Not enough values in WasmValue vector".to_string()))?) + .map_err(|_| Error::Other("Could not convert WasmValue to expected type".to_string())) } } }; diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index e17f866..ff9d061 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use core::fmt::Debug; use crate::{ @@ -10,10 +12,7 @@ use alloc::{ sync::Arc, vec::Vec, }; -use tinywasm_types::{ - Addr, Export, ExternVal, ExternalKind, FuncAddr, GlobalAddr, GlobalType, Import, MemAddr, MemoryType, - ModuleInstanceAddr, TableAddr, TableType, TypeAddr, WasmFunction, WasmValue, -}; +use tinywasm_types::*; /// The internal representation of a function #[derive(Debug, Clone)] @@ -39,9 +38,12 @@ impl Function { #[derive(Clone)] pub struct HostFunction { pub(crate) ty: tinywasm_types::FuncType, - pub(crate) func: Arc Result> + 'static + Send + Sync>, + pub(crate) func: HostFuncInner, } +pub(crate) type HostFuncInner = + Arc Result> + 'static + Send + Sync>; + impl Debug for HostFunction { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("HostFunction").field("ty", &self.ty).field("func", &"...").finish() @@ -208,7 +210,7 @@ impl Imports { pub(crate) fn take( &mut self, - store: &mut crate::Store, + _store: &mut crate::Store, import: &Import, ) -> Option> { let name = ExternName::from(import); diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 9ad1cfd..fb5f5b3 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -126,7 +126,7 @@ impl ModuleInstance { } pub(crate) fn func_ty(&self, addr: FuncAddr) -> &FuncType { - &self.0.types.get(addr as usize).expect("No func type for func, this is a bug") + self.0.types.get(addr as usize).expect("No func type for func, this is a bug") } // resolve a function address to the global store address @@ -161,7 +161,7 @@ impl ModuleInstance { }; let func_inst = store.get_func(func_addr as usize)?; - let ty = func_inst.func.ty(&self); + let ty = func_inst.func.ty(self); Ok(FuncHandle { addr: func_addr, module: self.clone(), name: Some(name.to_string()), ty: ty.clone() }) } @@ -203,7 +203,7 @@ impl ModuleInstance { let func_addr = self.0.func_addrs.get(func_index as usize).expect("No func addr for start func, this is a bug"); let func_inst = store.get_func(*func_addr as usize)?; - let ty = func_inst.func.ty(&self); + let ty = func_inst.func.ty(self); Ok(Some(FuncHandle { module: self.clone(), addr: *func_addr, ty, name: None })) } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index e7fc7b1..e9908d2 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -1,15 +1,10 @@ -#![allow(dead_code)] // TODO: remove this - use core::{ cell::RefCell, sync::atomic::{AtomicUsize, Ordering}, }; use alloc::{format, rc::Rc, string::ToString, vec, vec::Vec}; -use tinywasm_types::{ - Addr, Data, DataAddr, ElemAddr, Element, ElementKind, FuncAddr, Global, GlobalType, MemAddr, MemoryArch, - MemoryType, ModuleInstanceAddr, TableAddr, TableType, WasmFunction, -}; +use tinywasm_types::*; use crate::{ runtime::{self, DefaultRuntime}, @@ -49,7 +44,7 @@ impl Store { Self::default() } - pub(crate) fn get_module_instance(&self, addr: ModuleInstanceAddr) -> Option<&ModuleInstance> { + pub(crate) fn _get_module_instance(&self, addr: ModuleInstanceAddr) -> Option<&ModuleInstance> { self.module_instances.get(addr as usize) } @@ -118,7 +113,7 @@ impl Store { let func_count = self.data.funcs.len(); let mut func_addrs = Vec::with_capacity(func_count); for (i, func) in funcs.into_iter().enumerate() { - self.data.funcs.push(Rc::new(FunctionInstance { func: Function::Wasm(func), owner: idx })); + self.data.funcs.push(Rc::new(FunctionInstance { func: Function::Wasm(func), _owner: idx })); func_addrs.push((i + func_count) as FuncAddr); } Ok(func_addrs) @@ -155,9 +150,13 @@ impl Store { pub(crate) fn init_globals(&mut self, globals: Vec, idx: ModuleInstanceAddr) -> Result> { let global_count = self.data.globals.len(); let mut global_addrs = Vec::with_capacity(global_count); - // then add the module globals for (i, global) in globals.iter().enumerate() { - global_addrs.push(self.add_global(global.ty, self.eval_const(&global.init)?, idx)?.into()); + self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new( + global.ty, + self.eval_const(&global.init)?, + idx, + )))); + global_addrs.push((i + global_count) as Addr); } Ok(global_addrs) @@ -287,27 +286,8 @@ impl Store { Ok(self.data.mems.len() as MemAddr - 1) } - pub(crate) fn add_elem(&mut self, elem: Element, idx: ModuleInstanceAddr) -> Result { - let init = elem - .items - .iter() - .map(|item| { - item.addr() - .ok_or_else(|| Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item))) - }) - .collect::>>()?; - - self.data.elems.push(ElemInstance::new(elem.kind, idx, Some(init))); - Ok(self.data.elems.len() as ElemAddr - 1) - } - - pub(crate) fn add_data(&mut self, data: Data, idx: ModuleInstanceAddr) -> Result { - self.data.datas.push(DataInstance::new(data.data.to_vec(), idx)); - Ok(self.data.datas.len() as DataAddr - 1) - } - pub(crate) fn add_func(&mut self, func: Function, idx: ModuleInstanceAddr) -> Result { - self.data.funcs.push(Rc::new(FunctionInstance { func, owner: idx })); + self.data.funcs.push(Rc::new(FunctionInstance { func, _owner: idx })); Ok(self.data.funcs.len() as FuncAddr - 1) } @@ -362,10 +342,6 @@ impl Store { self.data.tables.get(addr).ok_or_else(|| Error::Other(format!("table {} not found", addr))) } - pub(crate) fn get_elem(&self, addr: usize) -> Result<&ElemInstance> { - self.data.elems.get(addr).ok_or_else(|| Error::Other(format!("element {} not found", addr))) - } - /// Get the global at the actual index in the store pub(crate) fn get_global_val(&self, addr: usize) -> Result { self.data @@ -390,7 +366,7 @@ impl Store { /// See pub struct FunctionInstance { pub(crate) func: Function, - pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions + pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions } // TODO: check if this actually helps @@ -415,14 +391,14 @@ impl FunctionInstance { /// See #[derive(Debug)] pub(crate) struct TableInstance { - pub(crate) kind: TableType, pub(crate) elements: Vec, - pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) _kind: TableType, + pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl TableInstance { pub(crate) fn new(kind: TableType, owner: ModuleInstanceAddr) -> Self { - Self { elements: vec![0; kind.size_initial as usize], kind, owner } + Self { elements: vec![0; kind.size_initial as usize], _kind: kind, _owner: owner } } pub(crate) fn get(&self, addr: usize) -> Result { @@ -468,7 +444,7 @@ pub(crate) struct MemoryInstance { pub(crate) kind: MemoryType, pub(crate) data: Vec, pub(crate) page_count: usize, - pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl MemoryInstance { @@ -480,7 +456,7 @@ impl MemoryInstance { kind, data: vec![0; PAGE_SIZE * kind.page_count_initial as usize], page_count: kind.page_count_initial as usize, - owner, + _owner: owner, } } @@ -556,14 +532,14 @@ impl MemoryInstance { /// See #[derive(Debug)] pub(crate) struct GlobalInstance { - pub(crate) ty: GlobalType, pub(crate) value: RawWasmValue, - owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) _ty: GlobalType, + pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl GlobalInstance { pub(crate) fn new(ty: GlobalType, value: RawWasmValue, owner: ModuleInstanceAddr) -> Self { - Self { ty, value, owner } + Self { _ty: ty, value, _owner: owner } } } @@ -572,14 +548,14 @@ impl GlobalInstance { /// See #[derive(Debug)] pub(crate) struct ElemInstance { - kind: ElementKind, - items: Option>, // none is the element was dropped - owner: ModuleInstanceAddr, // index into store.module_instances + _kind: ElementKind, + _items: Option>, // none is the element was dropped + _owner: ModuleInstanceAddr, // index into store.module_instances } impl ElemInstance { pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option>) -> Self { - Self { kind, owner, items } + Self { _kind: kind, _owner: owner, _items: items } } } @@ -588,12 +564,12 @@ impl ElemInstance { /// See #[derive(Debug)] pub(crate) struct DataInstance { - pub(crate) data: Vec, - owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) _data: Vec, + pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl DataInstance { pub(crate) fn new(data: Vec, owner: ModuleInstanceAddr) -> Self { - Self { data, owner } + Self { _data: data, _owner: owner } } } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 4d3c59a..965c97e 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -25,7 +25,7 @@ extern crate alloc; mod instructions; use core::{fmt::Debug, ops::Range}; -use alloc::{boxed::Box, sync::Arc, vec::Vec}; +use alloc::boxed::Box; pub use instructions::*; /// A TinyWasm WebAssembly Module From f59963d2b7b0b65af3b33e4ef3e465e8148760e7 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 13:39:59 +0100 Subject: [PATCH 20/52] fix: call param order Signed-off-by: Henry Gressmann --- crates/parser/src/conversion.rs | 161 ++++-------------- crates/tinywasm/src/runtime/executor/mod.rs | 17 +- .../tinywasm/src/runtime/stack/call_stack.rs | 16 +- .../tinywasm/src/runtime/stack/value_stack.rs | 10 ++ crates/tinywasm/src/runtime/value.rs | 16 +- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 8 +- crates/tinywasm/tests/testsuite/util.rs | 38 ++--- crates/types/src/lib.rs | 24 +-- 9 files changed, 99 insertions(+), 193 deletions(-) diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index b1427c0..4f79a4a 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -11,19 +11,13 @@ use crate::{module::CodeSection, Result}; pub(crate) fn convert_module_elements<'a, T: IntoIterator>>>( elements: T, ) -> Result> { - let elements = elements - .into_iter() - .map(|element| convert_module_element(element?)) - .collect::>>()?; + let elements = elements.into_iter().map(|element| convert_module_element(element?)).collect::>>()?; Ok(elements) } pub(crate) fn convert_module_element(element: wasmparser::Element<'_>) -> Result { let kind = match element.kind { - wasmparser::ElementKind::Active { - table_index, - offset_expr, - } => tinywasm_types::ElementKind::Active { + wasmparser::ElementKind::Active { table_index, offset_expr } => tinywasm_types::ElementKind::Active { table: table_index, offset: process_const_operators(offset_expr.get_operators_reader())?, }, @@ -32,38 +26,24 @@ pub(crate) fn convert_module_element(element: wasmparser::Element<'_>) -> Result }; let items = match element.items { - wasmparser::ElementItems::Functions(funcs) => funcs - .into_iter() - .map(|func| Ok(ElementItem::Func(func?))) - .collect::>>()? - .into_boxed_slice(), + wasmparser::ElementItems::Functions(funcs) => { + funcs.into_iter().map(|func| Ok(ElementItem::Func(func?))).collect::>>()?.into_boxed_slice() + } wasmparser::ElementItems::Expressions(exprs) => exprs .into_iter() - .map(|expr| { - Ok(ElementItem::Expr(process_const_operators( - expr?.get_operators_reader(), - )?)) - }) + .map(|expr| Ok(ElementItem::Expr(process_const_operators(expr?.get_operators_reader())?))) .collect::>>()? .into_boxed_slice(), }; - Ok(tinywasm_types::Element { - kind, - items, - ty: convert_valtype(&element.ty), - range: element.range, - }) + Ok(tinywasm_types::Element { kind, items, ty: convert_valtype(&element.ty), range: element.range }) } pub(crate) fn convert_module_data_sections<'a, T: IntoIterator>>>( data_sections: T, ) -> Result> { - let data_sections = data_sections - .into_iter() - .map(|data| convert_module_data(data?)) - .collect::>>()?; + let data_sections = data_sections.into_iter().map(|data| convert_module_data(data?)).collect::>>()?; Ok(data_sections) } @@ -72,15 +52,9 @@ pub(crate) fn convert_module_data(data: wasmparser::Data<'_>) -> Result { + wasmparser::DataKind::Active { memory_index, offset_expr } => { let offset = process_const_operators(offset_expr.get_operators_reader())?; - tinywasm_types::DataKind::Active { - mem: memory_index, - offset, - } + tinywasm_types::DataKind::Active { mem: memory_index, offset } } wasmparser::DataKind::Passive => tinywasm_types::DataKind::Passive, }, @@ -90,10 +64,7 @@ pub(crate) fn convert_module_data(data: wasmparser::Data<'_>) -> Result>>>( imports: T, ) -> Result> { - let imports = imports - .into_iter() - .map(|import| convert_module_import(import?)) - .collect::>>()?; + let imports = imports.into_iter().map(|import| convert_module_import(import?)).collect::>>()?; Ok(imports) } @@ -105,15 +76,11 @@ pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result ImportKind::Func(ty), wasmparser::TypeRef::Table(ty) => ImportKind::Table(convert_module_table(ty)?), wasmparser::TypeRef::Memory(ty) => ImportKind::Mem(convert_module_memory(ty)?), - wasmparser::TypeRef::Global(ty) => ImportKind::Global(GlobalType { - mutable: ty.mutable, - ty: convert_valtype(&ty.content_type), - }), + wasmparser::TypeRef::Global(ty) => { + ImportKind::Global(GlobalType { mutable: ty.mutable, ty: convert_valtype(&ty.content_type) }) + } wasmparser::TypeRef::Tag(ty) => { - return Err(crate::ParseError::UnsupportedOperator(format!( - "Unsupported import kind: {:?}", - ty - ))) + return Err(crate::ParseError::UnsupportedOperator(format!("Unsupported import kind: {:?}", ty))) } }, }) @@ -122,10 +89,8 @@ pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result>>( memory_types: T, ) -> Result> { - let memory_type = memory_types - .into_iter() - .map(|memory| convert_module_memory(memory?)) - .collect::>>()?; + let memory_type = + memory_types.into_iter().map(|memory| convert_module_memory(memory?)).collect::>>()?; Ok(memory_type) } @@ -144,21 +109,14 @@ pub(crate) fn convert_module_memory(memory: wasmparser::MemoryType) -> Result>>( table_types: T, ) -> Result> { - let table_type = table_types - .into_iter() - .map(|table| convert_module_table(table?)) - .collect::>>()?; + let table_type = table_types.into_iter().map(|table| convert_module_table(table?)).collect::>>()?; Ok(table_type) } pub(crate) fn convert_module_table(table: wasmparser::TableType) -> Result { let ty = convert_valtype(&table.element_type); - Ok(TableType { - element_type: ty, - size_initial: table.initial, - size_max: table.maximum, - }) + Ok(TableType { element_type: ty, size_initial: table.initial, size_max: table.maximum }) } pub(crate) fn convert_module_globals<'a, T: IntoIterator>>>( @@ -171,13 +129,7 @@ pub(crate) fn convert_module_globals<'a, T: IntoIterator>>()?; Ok(globals) @@ -190,18 +142,11 @@ pub(crate) fn convert_module_export(export: wasmparser::Export) -> Result ExternalKind::Memory, wasmparser::ExternalKind::Global => ExternalKind::Global, wasmparser::ExternalKind::Tag => { - return Err(crate::ParseError::UnsupportedOperator(format!( - "Unsupported export kind: {:?}", - export.kind - ))) + return Err(crate::ParseError::UnsupportedOperator(format!("Unsupported export kind: {:?}", export.kind))) } }; - Ok(Export { - index: export.index, - name: Box::from(export.name), - kind, - }) + Ok(Export { index: export.index, name: Box::from(export.name), kind }) } pub(crate) fn convert_module_code( @@ -224,27 +169,16 @@ pub(crate) fn convert_module_code( let body_reader = func.get_operators_reader()?; let body = process_operators(body_reader.original_position(), body_reader.into_iter(), validator)?; - Ok(CodeSection { - locals: locals.into_boxed_slice(), - body, - }) + Ok(CodeSection { locals: locals.into_boxed_slice(), body }) } pub(crate) fn convert_module_type(ty: wasmparser::Type) -> Result { let wasmparser::Type::Func(ty) = ty; - let params = ty - .params() - .iter() - .map(|p| Ok(convert_valtype(p))) - .collect::>>()? - .into_boxed_slice(); - - let results = ty - .results() - .iter() - .map(|p| Ok(convert_valtype(p))) - .collect::>>()? - .into_boxed_slice(); + let params = + ty.params().iter().map(|p| Ok(convert_valtype(p))).collect::>>()?.into_boxed_slice(); + + let results = + ty.results().iter().map(|p| Ok(convert_valtype(p))).collect::>>()?.into_boxed_slice(); Ok(FuncType { params, results }) } @@ -270,19 +204,14 @@ pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> ValType { I64 => ValType::I64, F32 => ValType::F32, F64 => ValType::F64, - V128 => ValType::V128, + V128 => unimplemented!("128-bit values are not supported yet"), FuncRef => ValType::FuncRef, ExternRef => ValType::ExternRef, } } pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemArg { - MemArg { - offset: memarg.offset, - align: memarg.align, - align_max: memarg.max_align, - mem_addr: memarg.memory, - } + MemArg { offset: memarg.offset, align: memarg.align, align_max: memarg.max_align, mem_addr: memarg.memory } } pub(crate) fn process_const_operators(ops: OperatorsReader) -> Result { @@ -306,10 +235,7 @@ pub fn process_const_operator(op: wasmparser::Operator) -> Result Ok(ConstInstruction::F32Const(f32::from_bits(value.bits()))), // TODO: check if this is correct wasmparser::Operator::F64Const { value } => Ok(ConstInstruction::F64Const(f64::from_bits(value.bits()))), // TODO: check if this is correct wasmparser::Operator::GlobalGet { global_index } => Ok(ConstInstruction::GlobalGet(global_index)), - op => Err(crate::ParseError::UnsupportedOperator(format!( - "Unsupported const instruction: {:?}", - op - ))), + op => Err(crate::ParseError::UnsupportedOperator(format!("Unsupported const instruction: {:?}", op))), } } @@ -332,9 +258,7 @@ pub fn process_operators<'a>( let res = match op { BrTable { targets } => { let def = targets.default(); - let targets = targets - .targets() - .collect::, wasmparser::BinaryReaderError>>()?; + let targets = targets.targets().collect::, wasmparser::BinaryReaderError>>()?; instructions.push(Instruction::BrTable(def, targets.len())); instructions.extend(targets.into_iter().map(Instruction::BrLabel)); continue; @@ -406,11 +330,7 @@ pub fn process_operators<'a>( BrIf { relative_depth } => Instruction::BrIf(relative_depth), Return => Instruction::Return, Call { function_index } => Instruction::Call(function_index), - CallIndirect { - type_index, - table_index, - .. - } => Instruction::CallIndirect(type_index, table_index), + CallIndirect { type_index, table_index, .. } => Instruction::CallIndirect(type_index, table_index), Drop => Instruction::Drop, Select => Instruction::Select(None), TypedSelect { ty } => Instruction::Select(Some(convert_valtype(&ty))), @@ -590,19 +510,13 @@ pub fn process_operators<'a>( TableGet { table } => Instruction::TableGet(table), TableSet { table } => Instruction::TableSet(table), TableInit { table, elem_index } => Instruction::TableInit(table, elem_index), - TableCopy { src_table, dst_table } => Instruction::TableCopy { - from: src_table, - to: dst_table, - }, + TableCopy { src_table, dst_table } => Instruction::TableCopy { from: src_table, to: dst_table }, TableGrow { table } => Instruction::TableGrow(table), TableSize { table } => Instruction::TableSize(table), TableFill { table } => Instruction::TableFill(table), op => { log::error!("Unsupported instruction: {:?}", op); - return Err(crate::ParseError::UnsupportedOperator(format!( - "Unsupported instruction: {:?}", - op - ))); + return Err(crate::ParseError::UnsupportedOperator(format!("Unsupported instruction: {:?}", op))); } }; @@ -610,10 +524,7 @@ pub fn process_operators<'a>( } if !labels_ptrs.is_empty() { - panic!( - "last_label_pointer should be None after processing all instructions: {:?}", - labels_ptrs - ); + panic!("last_label_pointer should be None after processing all instructions: {:?}", labels_ptrs); } validator.finish(offset)?; diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 1072577..5d6892a 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -111,7 +111,7 @@ fn exec_one( Nop => { /* do nothing */ } Unreachable => return Ok(ExecResult::Trap(crate::Trap::Unreachable)), // we don't need to include the call frame here because it's already on the stack Drop => stack.values.pop().map(|_| ())?, - Select(_) => { + Select(t) => { // due to validation, we know that the type of the values on the stack let cond: i32 = stack.values.pop()?.into(); let val2 = stack.values.pop()?; @@ -143,8 +143,7 @@ fn exec_one( debug!("params: {:?}", func_ty.params); debug!("stack: {:?}", stack.values); - let params = stack.values.pop_n(func_ty.params.len())?; - + let params = stack.values.pop_n_rev(func_ty.params.len())?; let call_frame = CallFrame::new_raw(func_idx as usize, ¶ms, func.locals.to_vec()); // push the call frame @@ -163,10 +162,11 @@ fn exec_one( let call_ty = module.func_ty(*type_addr); let func_idx = stack.values.pop_t::()?; - let func_addr = table.borrow().get(func_idx as usize)?; + let actual_func_addr = table.borrow().get(func_idx as usize)?; + let resolved_func_addr = module.resolve_func_addr(actual_func_addr); // prepare the call frame - let func_inst = store.get_func(func_addr as usize)?; + let func_inst = store.get_func(resolved_func_addr as usize)?; let func = match &func_inst.func { crate::Function::Wasm(ref f) => f, crate::Function::Host(host_func) => { @@ -185,9 +185,8 @@ fn exec_one( ); } - let params = stack.values.pop_n(func_ty.params.len())?; - - let call_frame = CallFrame::new_raw(func_addr as usize, ¶ms, func.locals.to_vec()); + let params = stack.values.pop_n_rev(func_ty.params.len())?; + let call_frame = CallFrame::new_raw(resolved_func_addr as usize, ¶ms, func.locals.to_vec()); // push the call frame cf.instr_ptr += 1; // skip the call instruction @@ -218,7 +217,7 @@ fn exec_one( cf.instr_ptr += *end_offset } } else { - log::info!("entering then"); + log::trace!("entering then"); cf.enter_label( LabelFrame { instr_ptr: cf.instr_ptr, diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index 28ea621..dc9c64d 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -16,10 +16,7 @@ pub(crate) struct CallStack { impl Default for CallStack { fn default() -> Self { - Self { - stack: Vec::with_capacity(CALL_STACK_SIZE), - top: 0, - } + Self { stack: Vec::with_capacity(CALL_STACK_SIZE), top: 0 } } } @@ -42,7 +39,7 @@ impl CallStack { pub(crate) fn push(&mut self, call_frame: CallFrame) -> Result<()> { assert!(self.top <= self.stack.len(), "stack is too small"); - log::info!("stack size: {}", self.stack.len()); + log::debug!("stack size: {}", self.stack.len()); if self.stack.len() >= CALL_STACK_MAX_SIZE { return Err(Trap::CallStackOverflow.into()); } @@ -96,8 +93,7 @@ impl CallFrame { self.instr_ptr = break_to.end_instr_ptr; // we also want to trim the label stack, including the block - self.labels - .truncate(self.labels.len() - (break_to_relative as usize + 1)); + self.labels.truncate(self.labels.len() - (break_to_relative as usize + 1)); } } @@ -119,11 +115,7 @@ impl CallFrame { } pub(crate) fn new(func_ptr: usize, params: &[WasmValue], local_types: Vec) -> Self { - CallFrame::new_raw( - func_ptr, - ¶ms.iter().map(|v| RawWasmValue::from(*v)).collect::>(), - local_types, - ) + CallFrame::new_raw(func_ptr, ¶ms.iter().map(|v| RawWasmValue::from(*v)).collect::>(), local_types) } #[inline] diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index 1021289..18fbe07 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -115,6 +115,16 @@ impl ValueStack { Ok(res) } + #[inline] + pub(crate) fn pop_n_rev(&mut self, n: usize) -> Result> { + if self.top < n { + return Err(Error::StackUnderflow); + } + self.top -= n; + let res = self.stack.drain(self.top..).collect::>(); + Ok(res) + } + #[inline] pub(crate) fn pop_n_const(&mut self) -> Result<[RawWasmValue; N]> { if self.top < N { diff --git a/crates/tinywasm/src/runtime/value.rs b/crates/tinywasm/src/runtime/value.rs index 9b0b074..c01617e 100644 --- a/crates/tinywasm/src/runtime/value.rs +++ b/crates/tinywasm/src/runtime/value.rs @@ -27,9 +27,14 @@ impl RawWasmValue { ValType::I64 => WasmValue::I64(self.0 as i64), ValType::F32 => WasmValue::F32(f32::from_bits(self.0 as u32)), ValType::F64 => WasmValue::F64(f64::from_bits(self.0)), - ValType::ExternRef => WasmValue::RefExtern(self.0 as u32), - ValType::FuncRef => WasmValue::RefFunc(self.0 as u32), - ValType::V128 => todo!("v128"), + ValType::ExternRef => WasmValue::RefExtern(match self.0 { + 0 => None, + _ => Some(self.0 as u32), + }), + ValType::FuncRef => WasmValue::RefFunc(match self.0 { + 0 => None, + _ => Some(self.0 as u32), + }), } } } @@ -41,9 +46,8 @@ impl From for RawWasmValue { WasmValue::I64(i) => Self(i as u64), WasmValue::F32(i) => Self(i.to_bits() as u64), WasmValue::F64(i) => Self(i.to_bits()), - WasmValue::RefNull(v) => v.default_value().into(), - WasmValue::RefExtern(v) => Self(v as u64), - WasmValue::RefFunc(v) => Self(v as u64), + WasmValue::RefExtern(v) => Self(v.unwrap_or(0) as u64), + WasmValue::RefFunc(v) => Self(v.unwrap_or(0) as u64), } } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 824bf55..d5389e1 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19831,397,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":76,"failed":15},{"name":"call_indirect.wast","passed":155,"failed":15},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":69,"failed":30},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":170,"failed":2},{"name":"func_ptrs.wast","passed":20,"failed":16},{"name":"global.wast","passed":106,"failed":4},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":232,"failed":9},{"name":"imports.wast","passed":70,"failed":113},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":92,"failed":4},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":143,"failed":5},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19969,259,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":79,"failed":20},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":119,"failed":1},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 1f8316a..a631dce 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (19831) +v0.3.0-alpha.0 (19969) - - - + + + diff --git a/crates/tinywasm/tests/testsuite/util.rs b/crates/tinywasm/tests/testsuite/util.rs index 17bca76..bb134d2 100644 --- a/crates/tinywasm/tests/testsuite/util.rs +++ b/crates/tinywasm/tests/testsuite/util.rs @@ -4,19 +4,11 @@ use eyre::{eyre, Result}; use tinywasm_types::{TinyWasmModule, WasmValue}; pub fn try_downcast_panic(panic: Box) -> String { - let info = panic - .downcast_ref::() - .or(None) - .map(|p| p.to_string()) - .clone(); + let info = panic.downcast_ref::().or(None).map(|p| p.to_string()).clone(); let info_string = panic.downcast_ref::().cloned(); let info_str = panic.downcast::<&str>().ok().map(|s| *s); - info.unwrap_or( - info_str - .unwrap_or(&info_string.unwrap_or("unknown panic".to_owned())) - .to_string(), - ) + info.unwrap_or(info_str.unwrap_or(&info_string.unwrap_or("unknown panic".to_owned())).to_string()) } pub fn exec_fn_instance( @@ -73,12 +65,12 @@ pub fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result WasmValue::F64(f64::from_bits(f.bits)), I32(i) => WasmValue::I32(i), I64(i) => WasmValue::I64(i), - RefExtern(v) => WasmValue::RefExtern(v), - RefNull(t) => WasmValue::RefNull(match t { - wast::core::HeapType::Func => tinywasm_types::ValType::FuncRef, - wast::core::HeapType::Extern => tinywasm_types::ValType::ExternRef, + RefExtern(v) => WasmValue::RefExtern(Some(v)), + RefNull(t) => match t { + wast::core::HeapType::Func => WasmValue::RefFunc(None), + wast::core::HeapType::Extern => WasmValue::RefExtern(None), _ => return Err(eyre!("unsupported arg type: refnull: {:?}", t)), - }), + }, v => return Err(eyre!("unsupported arg type: {:?}", v)), }) } @@ -94,14 +86,18 @@ pub fn wastret2tinywasmvalue(arg: wast::WastRet) -> Result nanpattern2tinywasmvalue(f)?, I32(i) => WasmValue::I32(i), I64(i) => WasmValue::I64(i), - RefNull(t) => WasmValue::RefNull(match t { - Some(wast::core::HeapType::Func) => tinywasm_types::ValType::FuncRef, - Some(wast::core::HeapType::Extern) => tinywasm_types::ValType::ExternRef, + RefNull(t) => match t { + Some(wast::core::HeapType::Func) => WasmValue::RefFunc(None), + Some(wast::core::HeapType::Extern) => WasmValue::RefExtern(None), _ => return Err(eyre!("unsupported arg type: refnull: {:?}", t)), - }), + }, RefExtern(v) => match v { - Some(v) => WasmValue::RefExtern(v), - None => WasmValue::RefNull(tinywasm_types::ValType::ExternRef), + Some(v) => WasmValue::RefExtern(Some(v)), + _ => return Err(eyre!("unsupported arg type: refextern: {:?}", v)), + }, + RefFunc(v) => match v { + Some(wast::token::Index::Num(n, _)) => WasmValue::RefFunc(Some(n)), + _ => return Err(eyre!("unsupported arg type: reffunc: {:?}", v)), }, a => return Err(eyre!("unsupported arg type {:?}", a)), }) diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 965c97e..29aa5d7 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -86,9 +86,8 @@ pub enum WasmValue { // Vec types // V128(i128), // RefHost(FuncAddr), - RefExtern(ExternAddr), - RefNull(ValType), - RefFunc(FuncAddr), + RefExtern(Option), + RefFunc(Option), } impl WasmValue { @@ -98,7 +97,8 @@ impl WasmValue { Self::I64(i) => ConstInstruction::I64Const(*i), Self::F32(i) => ConstInstruction::F32Const(*i), Self::F64(i) => ConstInstruction::F64Const(*i), - Self::RefNull(ty) => ConstInstruction::RefNull(*ty), + Self::RefExtern(None) => ConstInstruction::RefNull(ValType::ExternRef), + Self::RefFunc(None) => ConstInstruction::RefNull(ValType::FuncRef), // Self::RefExtern(addr) => ConstInstruction::RefExtern(*addr), _ => unimplemented!("no const_instr for {:?}", self), } @@ -111,9 +111,8 @@ impl WasmValue { ValType::I64 => Self::I64(0), ValType::F32 => Self::F32(0.0), ValType::F64 => Self::F64(0.0), - ValType::V128 => unimplemented!("V128 is not yet supported"), - ValType::FuncRef => Self::RefFunc(0), - ValType::ExternRef => Self::RefExtern(0), + ValType::FuncRef => Self::RefFunc(None), + ValType::ExternRef => Self::RefExtern(None), } } @@ -121,8 +120,8 @@ impl WasmValue { match (self, other) { (Self::I32(a), Self::I32(b)) => a == b, (Self::I64(a), Self::I64(b)) => a == b, - (Self::RefNull(ty), Self::RefNull(ty2)) => ty == ty2, (Self::RefExtern(addr), Self::RefExtern(addr2)) => addr == addr2, + (Self::RefFunc(addr), Self::RefFunc(addr2)) => addr == addr2, (Self::F32(a), Self::F32(b)) => { if a.is_nan() && b.is_nan() { true // Both are NaN, treat them as equal @@ -217,9 +216,8 @@ impl Debug for WasmValue { WasmValue::I64(i) => write!(f, "i64({})", i), WasmValue::F32(i) => write!(f, "f32({})", i), WasmValue::F64(i) => write!(f, "f64({})", i), - WasmValue::RefNull(ty) => write!(f, "ref.null({:?})", ty), - WasmValue::RefExtern(addr) => write!(f, "ref.extern({})", addr), - WasmValue::RefFunc(addr) => write!(f, "ref.func({})", addr), + WasmValue::RefExtern(addr) => write!(f, "ref.extern({:?})", addr), + WasmValue::RefFunc(addr) => write!(f, "ref.func({:?})", addr), // WasmValue::V128(i) => write!(f, "v128({})", i), } } @@ -233,10 +231,8 @@ impl WasmValue { Self::I64(_) => ValType::I64, Self::F32(_) => ValType::F32, Self::F64(_) => ValType::F64, - Self::RefNull(ty) => *ty, Self::RefExtern(_) => ValType::ExternRef, Self::RefFunc(_) => ValType::FuncRef, - // Self::V128(_) => ValType::V128, } } } @@ -252,8 +248,6 @@ pub enum ValType { F32, /// A 64-bit float. F64, - /// A 128-bit vector. - V128, /// A reference to a function. FuncRef, /// A reference to an external value. From 85deebcc058c9958f83cd68ddb861e2dde9a3a62 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 14:17:38 +0100 Subject: [PATCH 21/52] fix: breaking in loops Signed-off-by: Henry Gressmann --- crates/tinywasm/src/runtime/executor/mod.rs | 44 ++++++++++--------- .../tinywasm/src/runtime/executor/traits.rs | 1 - .../tinywasm/src/runtime/stack/call_stack.rs | 11 ++++- .../tinywasm/src/runtime/stack/value_stack.rs | 1 + crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 4 +- crates/tinywasm/tests/test-mvp.rs | 7 +-- crates/tinywasm/tests/test-wast.rs | 14 ++---- 8 files changed, 40 insertions(+), 44 deletions(-) diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 5d6892a..f5193f4 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -198,25 +198,8 @@ fn exec_one( } If(args, else_offset, end_offset) => { - if stack.values.pop_t::()? == 0 { - if let Some(else_offset) = else_offset { - log::debug!("entering else at {}", cf.instr_ptr + *else_offset); - cf.enter_label( - LabelFrame { - instr_ptr: cf.instr_ptr + *else_offset, - end_instr_ptr: cf.instr_ptr + *end_offset, - stack_ptr: stack.values.len(), // - params, - args: crate::LabelArgs::new(*args, module)?, - ty: BlockType::Else, - }, - &mut stack.values, - ); - cf.instr_ptr += *else_offset; - } else { - log::info!("skipping if"); - cf.instr_ptr += *end_offset - } - } else { + // truthy value is on the top of the stack, so enter the then block + if stack.values.pop_t::()? != 0 { log::trace!("entering then"); cf.enter_label( LabelFrame { @@ -227,7 +210,26 @@ fn exec_one( ty: BlockType::If, }, &mut stack.values, - ) + ); + return Ok(ExecResult::Ok); + } + + // falsy value is on the top of the stack + if let Some(else_offset) = else_offset { + log::debug!("entering else at {}", cf.instr_ptr + *else_offset); + cf.enter_label( + LabelFrame { + instr_ptr: cf.instr_ptr + *else_offset, + end_instr_ptr: cf.instr_ptr + *end_offset, + stack_ptr: stack.values.len(), // - params, + args: crate::LabelArgs::new(*args, module)?, + ty: BlockType::Else, + }, + &mut stack.values, + ); + cf.instr_ptr += *else_offset; + } else { + cf.instr_ptr += *end_offset; } } @@ -285,7 +287,7 @@ fn exec_one( Br(v) => break_to!(cf, stack, v), BrIf(v) => { - if stack.values.pop_t::()? > 0 { + if stack.values.pop_t::()? != 0 { break_to!(cf, stack, v); } } diff --git a/crates/tinywasm/src/runtime/executor/traits.rs b/crates/tinywasm/src/runtime/executor/traits.rs index 9bddba1..c8733d3 100644 --- a/crates/tinywasm/src/runtime/executor/traits.rs +++ b/crates/tinywasm/src/runtime/executor/traits.rs @@ -16,7 +16,6 @@ macro_rules! impl_wasm_float_ops { impl WasmFloatOps for $t { // https://webassembly.github.io/spec/core/exec/numerics.html#op-fnearest fn wasm_nearest(self) -> Self { - log::info!("wasm_nearest: {}", self); match self { x if x.is_nan() => x, x if x.is_infinite() || x == 0.0 => x, diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index dc9c64d..6eb72b5 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -75,21 +75,28 @@ impl CallFrame { /// Returns `None` if there is no block at the given index (e.g. if we need to return, this is handled by the caller) #[inline] pub(crate) fn break_to(&mut self, break_to_relative: u32, value_stack: &mut super::ValueStack) -> Option<()> { + log::debug!("break_to_relative: {}", break_to_relative); let break_to = self.labels.get_relative_to_top(break_to_relative as usize)?; - value_stack.break_to(break_to.stack_ptr, break_to.args.results); // instr_ptr points to the label instruction, but the next step // will increment it by 1 since we're changing the "current" instr_ptr match break_to.ty { BlockType::Loop => { // this is a loop, so we want to jump back to the start of the loop + // We also want to push the params to the stack + value_stack.break_to(break_to.stack_ptr, break_to.args.params); + self.instr_ptr = break_to.instr_ptr; // we also want to trim the label stack to the loop (but not including the loop) self.labels.truncate(self.labels.len() - break_to_relative as usize); } BlockType::Block | BlockType::If | BlockType::Else => { - // this is a block, so we want to jump to the next instruction after the block ends (the inst_ptr will be incremented by 1 before the next instruction is executed) + // this is a block, so we want to jump to the next instruction after the block ends + // We also want to push the block's results to the stack + value_stack.break_to(break_to.stack_ptr, break_to.args.results); + + // (the inst_ptr will be incremented by 1 before the next instruction is executed) self.instr_ptr = break_to.end_instr_ptr; // we also want to trim the label stack, including the block diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index 18fbe07..9edfb51 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -92,6 +92,7 @@ impl ValueStack { } pub(crate) fn break_to(&mut self, new_stack_size: usize, result_count: usize) { + assert!(self.top >= result_count); self.stack.copy_within((self.top - result_count)..self.top, new_stack_size); self.top = new_stack_size + result_count; self.stack.truncate(self.top); diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index d5389e1..b36f0c6 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19969,259,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":79,"failed":20},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":7,"failed":1},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":119,"failed":1},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19974,254,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":79,"failed":20},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index a631dce..d36a155 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (19969) +v0.3.0-alpha.0 (19974) - + diff --git a/crates/tinywasm/tests/test-mvp.rs b/crates/tinywasm/tests/test-mvp.rs index 5107551..445b7fa 100644 --- a/crates/tinywasm/tests/test-mvp.rs +++ b/crates/tinywasm/tests/test-mvp.rs @@ -17,16 +17,11 @@ fn test_mvp() -> Result<()> { TestSuite::set_log_level(log::LevelFilter::Off); test_suite.run_spec_group(wasm_testsuite::MVP_TESTS)?; - test_suite.save_csv("./tests/generated/mvp.csv", env!("CARGO_PKG_VERSION"))?; if test_suite.failed() { println!(); - Err(eyre!(format!( - "{}:\n{:#?}", - "failed one or more tests".red().bold(), - test_suite, - ))) + Err(eyre!(format!("{}:\n{:#?}", "failed one or more tests".red().bold(), test_suite,))) } else { println!("\n\npassed all tests:\n{:#?}", test_suite); Ok(()) diff --git a/crates/tinywasm/tests/test-wast.rs b/crates/tinywasm/tests/test-wast.rs index 56bb39e..a50a612 100644 --- a/crates/tinywasm/tests/test-wast.rs +++ b/crates/tinywasm/tests/test-wast.rs @@ -20,11 +20,7 @@ fn main() -> Result<()> { let cwd = std::env::current_dir()?; // if current dir is crates/tinywasm, then we want to go up 2 levels - let mut wast_file = if cwd.ends_with("crates/tinywasm") { - PathBuf::from("../../") - } else { - PathBuf::from("./") - }; + let mut wast_file = if cwd.ends_with("crates/tinywasm") { PathBuf::from("../../") } else { PathBuf::from("./") }; wast_file.push(&args[2]); let wast_file = cwd.join(wast_file); @@ -34,7 +30,7 @@ fn main() -> Result<()> { } fn test_wast(wast_file: &str) -> Result<()> { - TestSuite::set_log_level(log::LevelFilter::Info); + TestSuite::set_log_level(log::LevelFilter::Debug); let args = std::env::args().collect::>(); println!("args: {:?}", args); @@ -48,11 +44,7 @@ fn test_wast(wast_file: &str) -> Result<()> { println!(); test_suite.print_errors(); println!(); - Err(eyre!(format!( - "{}:\n{:#?}", - "failed one or more tests".red().bold(), - test_suite, - ))) + Err(eyre!(format!("{}:\n{:#?}", "failed one or more tests".red().bold(), test_suite,))) } else { println!("\n\npassed all tests:\n{:#?}", test_suite); Ok(()) From 4125110dea81489bed2d8cf9d6f9f3d27c51eb86 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 14:36:25 +0100 Subject: [PATCH 22/52] feat: table.init Signed-off-by: Henry Gressmann --- crates/tinywasm/src/instance.rs | 5 ++++ crates/tinywasm/src/runtime/executor/mod.rs | 26 +++++++++++++++++-- .../tinywasm/src/runtime/stack/value_stack.rs | 10 ------- crates/tinywasm/src/store.rs | 13 +++++++--- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 6 ++--- crates/types/src/lib.rs | 2 +- 7 files changed, 43 insertions(+), 21 deletions(-) diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index fb5f5b3..ead3439 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -144,6 +144,11 @@ impl ModuleInstance { *self.0.mem_addrs.get(addr as usize).expect("No mem addr for mem, this is a bug") } + // resolve a memory address to the global store address + pub(crate) fn resolve_elem_addr(&self, addr: ElemAddr) -> ElemAddr { + *self.0.elem_addrs.get(addr as usize).expect("No elem addr for elem, this is a bug") + } + // resolve a global address to the global store address pub(crate) fn resolve_global_addr(&self, addr: GlobalAddr) -> GlobalAddr { self.0.global_addrs[addr as usize] diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index f5193f4..8b4f0e2 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -7,7 +7,7 @@ use crate::{ CallFrame, Error, LabelArgs, ModuleInstance, Result, Store, Trap, }; use alloc::{string::ToString, vec::Vec}; -use tinywasm_types::Instruction; +use tinywasm_types::{ElementKind, Instruction}; mod macros; mod traits; @@ -111,7 +111,10 @@ fn exec_one( Nop => { /* do nothing */ } Unreachable => return Ok(ExecResult::Trap(crate::Trap::Unreachable)), // we don't need to include the call frame here because it's already on the stack Drop => stack.values.pop().map(|_| ())?, - Select(t) => { + + Select( + _valtype, // due to validation, we know that the type of the values on the stack are correct + ) => { // due to validation, we know that the type of the values on the stack let cond: i32 = stack.values.pop()?.into(); let val2 = stack.values.pop()?; @@ -554,6 +557,7 @@ fn exec_one( I64TruncF32U => checked_conv_float!(f32, u64, i64, stack), I64TruncF64U => checked_conv_float!(f64, u64, i64, stack), + // TODO: uninitialized element traps TableGet(table_index) => { let table_idx = module.resolve_table_addr(*table_index); let table = store.get_table(table_idx as usize)?; @@ -575,6 +579,24 @@ fn exec_one( stack.values.push(table.borrow().size().into()); } + TableInit(table_index, elem_index) => { + let table_idx = module.resolve_table_addr(*table_index); + let table = store.get_table(table_idx as usize)?; + + let elem_idx = module.resolve_elem_addr(*elem_index); + let elem = store.get_elem(elem_idx as usize)?; + + if elem.kind != ElementKind::Passive { + return Err(Trap::TableOutOfBounds { offset: 0, len: 0, max: 0 }.into()); + } + + let Some(items) = elem.items.as_ref() else { + return Err(Trap::TableOutOfBounds { offset: 0, len: 0, max: 0 }.into()); + }; + + table.borrow_mut().init(0, items)?; + } + I32TruncSatF32S => arithmetic_single!(trunc, f32, i32, stack), I32TruncSatF32U => arithmetic_single!(trunc, f32, u32, stack), I32TruncSatF64S => arithmetic_single!(trunc, f64, i32, stack), diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index 9edfb51..7b4613d 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -106,16 +106,6 @@ impl ValueStack { Ok(&self.stack[self.top - n..self.top]) } - #[inline] - pub(crate) fn pop_n(&mut self, n: usize) -> Result> { - if self.top < n { - return Err(Error::StackUnderflow); - } - self.top -= n; - let res = self.stack.drain(self.top..).rev().collect::>(); - Ok(res) - } - #[inline] pub(crate) fn pop_n_rev(&mut self, n: usize) -> Result> { if self.top < n { diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index e9908d2..36ba8d9 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -342,6 +342,11 @@ impl Store { self.data.tables.get(addr).ok_or_else(|| Error::Other(format!("table {} not found", addr))) } + /// Get the element at the actual index in the store + pub(crate) fn get_elem(&self, addr: usize) -> Result<&ElemInstance> { + self.data.elems.get(addr).ok_or_else(|| Error::Other(format!("element {} not found", addr))) + } + /// Get the global at the actual index in the store pub(crate) fn get_global_val(&self, addr: usize) -> Result { self.data @@ -548,14 +553,14 @@ impl GlobalInstance { /// See #[derive(Debug)] pub(crate) struct ElemInstance { - _kind: ElementKind, - _items: Option>, // none is the element was dropped - _owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) kind: ElementKind, + pub(crate) items: Option>, // none is the element was dropped + _owner: ModuleInstanceAddr, // index into store.module_instances } impl ElemInstance { pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option>) -> Self { - Self { _kind: kind, _owner: owner, _items: items } + Self { kind, _owner: owner, items } } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index b36f0c6..91fde3c 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19974,254,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":79,"failed":20},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19976,252,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":81,"failed":18},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index d36a155..ed1fd54 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (19974) +v0.3.0-alpha.0 (19976) - + - + diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 29aa5d7..a9cbdcd 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -465,7 +465,7 @@ pub struct Element { pub ty: ValType, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum ElementKind { Passive, Active { table: TableAddr, offset: ConstInstruction }, From 255974ec5a675ffa1c4efaf13c6e6930a3a13d7e Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 14:49:39 +0100 Subject: [PATCH 23/52] fix: memory grow returns Signed-off-by: Henry Gressmann --- crates/tinywasm/src/runtime/executor/mod.rs | 4 ++-- crates/tinywasm/src/store.rs | 18 +++++++++++------- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 10 +++++----- crates/tinywasm/tests/test-wast.rs | 2 +- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 8b4f0e2..623f857 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -376,8 +376,8 @@ fn exec_one( }; match res { - Ok(_) => stack.values.push(prev_size.into()), - Err(_) => stack.values.push((-1).into()), + Some(_) => stack.values.push(prev_size.into()), + None => stack.values.push((-1).into()), } } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 36ba8d9..c3a1a6c 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -506,21 +506,25 @@ impl MemoryInstance { self.page_count as i32 } - pub(crate) fn grow(&mut self, delta: i32) -> Result { + pub(crate) fn grow(&mut self, delta: i32) -> Option { let current_pages = self.size(); let new_pages = current_pages + delta; + if new_pages < 0 || new_pages > MAX_PAGES as i32 { - return Err(Error::Other(format!("memory size out of bounds: {}", new_pages))); + return None; } - let new_size = new_pages as usize * PAGE_SIZE; - if self.max_pages() < new_pages as usize { - return Ok(current_pages); + if new_pages as usize > self.max_pages() { + log::info!("memory size out of bounds: {}", new_pages); + return None; } + let new_size = new_pages as usize * PAGE_SIZE; if new_size > MAX_SIZE { - return Err(Error::Other(format!("memory size out of bounds: {}", new_size))); + return None; } + + // Zero initialize the new pages self.data.resize(new_size, 0); self.page_count = new_pages as usize; @@ -528,7 +532,7 @@ impl MemoryInstance { log::debug!("memory grown by {} pages", delta); log::debug!("memory grown to {} pages", self.page_count); - Ok(current_pages) + Some(current_pages) } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 91fde3c..aa28697 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19976,252,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":81,"failed":18},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":95,"failed":1},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19978,250,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":81,"failed":18},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":75,"failed":108},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index ed1fd54..f04d5ab 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (19976) +v0.3.0-alpha.0 (19978) - - - - + + + + diff --git a/crates/tinywasm/tests/test-wast.rs b/crates/tinywasm/tests/test-wast.rs index a50a612..a0825b0 100644 --- a/crates/tinywasm/tests/test-wast.rs +++ b/crates/tinywasm/tests/test-wast.rs @@ -30,7 +30,7 @@ fn main() -> Result<()> { } fn test_wast(wast_file: &str) -> Result<()> { - TestSuite::set_log_level(log::LevelFilter::Debug); + TestSuite::set_log_level(log::LevelFilter::Info); let args = std::env::args().collect::>(); println!("args: {:?}", args); From 01f4fdfee71df48b427d6abbfd454c82c50cacfd Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 14:56:53 +0100 Subject: [PATCH 24/52] fix: float rounding edgecase Signed-off-by: Henry Gressmann --- Cargo.lock | 4 ++-- .../tinywasm/src/runtime/executor/traits.rs | 23 ++++++++++++++++--- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 8 +++---- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32ebc37..ec25d02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1401,9 +1401,9 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "winapi" diff --git a/crates/tinywasm/src/runtime/executor/traits.rs b/crates/tinywasm/src/runtime/executor/traits.rs index c8733d3..06aab2a 100644 --- a/crates/tinywasm/src/runtime/executor/traits.rs +++ b/crates/tinywasm/src/runtime/executor/traits.rs @@ -17,11 +17,28 @@ macro_rules! impl_wasm_float_ops { // https://webassembly.github.io/spec/core/exec/numerics.html#op-fnearest fn wasm_nearest(self) -> Self { match self { - x if x.is_nan() => x, - x if x.is_infinite() || x == 0.0 => x, + x if x.is_nan() => x, // preserve NaN + x if x.is_infinite() || x == 0.0 => x, // preserve infinities and zeros x if (0.0..=0.5).contains(&x) => 0.0, x if (-0.5..0.0).contains(&x) => -0.0, - x => x.round(), + // x => x.round(), + x => { + // Handle normal and halfway cases + let rounded = x.round(); + let diff = (x - rounded).abs(); + + if diff == 0.5 { + // Halfway case: round to even + if rounded % 2.0 == 0.0 { + rounded // Already even + } else { + rounded - x.signum() // Make even + } + } else { + // Normal case + rounded + } + } } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index aa28697..98a5a76 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19978,250,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":81,"failed":18},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":75,"failed":108},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,19982,246,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":81,"failed":18},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":75,"failed":108},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index f04d5ab..8ab81a8 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (19978) +v0.3.0-alpha.0 (19982) - - - + + + From f7fe87184a29dc1126e0f142accf4ff518aa02cf Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 16:55:58 +0100 Subject: [PATCH 25/52] feat: add FuncContext Signed-off-by: Henry Gressmann --- crates/tinywasm/src/func.rs | 5 +- crates/tinywasm/src/imports.rs | 50 +++++++-- crates/tinywasm/src/runtime/executor/mod.rs | 6 +- crates/tinywasm/tests/testsuite/run.rs | 107 ++++++++------------ 4 files changed, 89 insertions(+), 79 deletions(-) diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 8546b9f..87259f5 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -4,7 +4,7 @@ use tinywasm_types::{FuncAddr, FuncType, ValType, WasmValue}; use crate::{ runtime::{CallFrame, Stack}, - Error, ModuleInstance, Result, Store, + Error, FuncContext, ModuleInstance, Result, Store, }; #[derive(Debug)] @@ -55,7 +55,8 @@ impl FuncHandle { let wasm_func = match &func_inst.func { crate::Function::Host(h) => { let func = h.func.clone(); - return (func)(store, params); + let ctx = FuncContext { store, module: &self.module }; + return (func)(ctx, params); } crate::Function::Wasm(ref f) => f, }; diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index ff9d061..683f65a 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -41,8 +41,44 @@ pub struct HostFunction { pub(crate) func: HostFuncInner, } +impl HostFunction { + /// Get the function's type + pub fn ty(&self) -> &tinywasm_types::FuncType { + &self.ty + } + + /// Call the function + pub fn call(&self, ctx: FuncContext<'_>, args: &[WasmValue]) -> Result> { + (self.func)(ctx, args) + } +} + pub(crate) type HostFuncInner = - Arc Result> + 'static + Send + Sync>; + Arc, &[WasmValue]) -> Result> + 'static + Send + Sync>; + +/// The context of a host-function call +#[derive(Debug)] +pub struct FuncContext<'a> { + pub(crate) store: &'a mut crate::Store, + pub(crate) module: &'a crate::ModuleInstance, +} + +impl FuncContext<'_> { + /// Get a mutable reference to the store + pub fn store_mut(&mut self) -> &mut crate::Store { + self.store + } + + /// Get a reference to the store + pub fn store(&self) -> &crate::Store { + self.store + } + + /// Get a reference to the module instance + pub fn module(&self) -> &crate::ModuleInstance { + self.module + } +} impl Debug for HostFunction { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -110,25 +146,25 @@ impl Extern { /// Create a new function import pub fn func( ty: &tinywasm_types::FuncType, - func: impl Fn(&mut crate::Store, &[WasmValue]) -> Result> + 'static + Send + Sync, + func: impl Fn(FuncContext<'_>, &[WasmValue]) -> Result> + 'static + Send + Sync, ) -> Self { - let inner_func = move |store: &mut crate::Store, args: &[WasmValue]| { + let inner_func = move |ctx: FuncContext<'_>, args: &[WasmValue]| { let args = args.to_vec(); - func(store, &args) + func(ctx, &args) }; Self::Func(Function::Host(HostFunction { func: Arc::new(inner_func), ty: ty.clone() })) } /// Create a new typed function import - pub fn typed_func(func: impl Fn(&mut crate::Store, P) -> Result + 'static + Send + Sync) -> Self + pub fn typed_func(func: impl Fn(FuncContext<'_>, P) -> Result + 'static + Send + Sync) -> Self where P: FromWasmValueTuple + ValTypesFromTuple, R: IntoWasmValueTuple + ValTypesFromTuple, { - let inner_func = move |store: &mut crate::Store, args: &[WasmValue]| -> Result> { + let inner_func = move |ctx: FuncContext<'_>, args: &[WasmValue]| -> Result> { let args = P::from_wasm_value_tuple(args.to_vec())?; - let result = func(store, args)?; + let result = func(ctx, args)?; Ok(result.into_wasm_value_tuple()) }; diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 623f857..80ad4b4 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -4,7 +4,7 @@ use super::{DefaultRuntime, Stack}; use crate::{ log::debug, runtime::{BlockType, LabelFrame}, - CallFrame, Error, LabelArgs, ModuleInstance, Result, Store, Trap, + CallFrame, Error, FuncContext, LabelArgs, ModuleInstance, Result, Store, Trap, }; use alloc::{string::ToString, vec::Vec}; use tinywasm_types::{ElementKind, Instruction}; @@ -136,7 +136,7 @@ fn exec_one( crate::Function::Host(host_func) => { let func = host_func.func.clone(); let params = stack.values.pop_params(&host_func.ty.params)?; - let res = (func)(store, ¶ms)?; + let res = (func)(FuncContext { store, module }, ¶ms)?; stack.values.extend_from_typed(&res); return Ok(ExecResult::Ok); } @@ -175,7 +175,7 @@ fn exec_one( crate::Function::Host(host_func) => { let func = host_func.func.clone(); let params = stack.values.pop_params(&host_func.ty.params)?; - let res = (func)(store, ¶ms)?; + let res = (func)(FuncContext { store, module }, ¶ms)?; stack.values.extend_from_typed(&res); return Ok(ExecResult::Ok); } diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index d2eab6c..d41ddca 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -22,42 +22,40 @@ impl TestSuite { fn imports(registered_modules: Vec<(String, ModuleInstanceAddr)>) -> Result { let mut imports = Imports::new(); - let table = Extern::table( - TableType::new(ValType::FuncRef, 10, Some(20)), - WasmValue::default_for(ValType::FuncRef), - ); + let table = + Extern::table(TableType::new(ValType::FuncRef, 10, Some(20)), WasmValue::default_for(ValType::FuncRef)); - let print = Extern::typed_func(|_: &mut tinywasm::Store, _: ()| { + let print = Extern::typed_func(|_ctx: tinywasm::FuncContext, _: ()| { log::debug!("print"); Ok(()) }); - let print_i32 = Extern::typed_func(|_: &mut tinywasm::Store, arg: i32| { + let print_i32 = Extern::typed_func(|_ctx: tinywasm::FuncContext, arg: i32| { log::debug!("print_i32: {}", arg); Ok(()) }); - let print_i64 = Extern::typed_func(|_: &mut tinywasm::Store, arg: i64| { + let print_i64 = Extern::typed_func(|_ctx: tinywasm::FuncContext, arg: i64| { log::debug!("print_i64: {}", arg); Ok(()) }); - let print_f32 = Extern::typed_func(|_: &mut tinywasm::Store, arg: f32| { + let print_f32 = Extern::typed_func(|_ctx: tinywasm::FuncContext, arg: f32| { log::debug!("print_f32: {}", arg); Ok(()) }); - let print_f64 = Extern::typed_func(|_: &mut tinywasm::Store, arg: f64| { + let print_f64 = Extern::typed_func(|_ctx: tinywasm::FuncContext, arg: f64| { log::debug!("print_f64: {}", arg); Ok(()) }); - let print_i32_f32 = Extern::typed_func(|_: &mut tinywasm::Store, args: (i32, f32)| { + let print_i32_f32 = Extern::typed_func(|_ctx: tinywasm::FuncContext, args: (i32, f32)| { log::debug!("print_i32_f32: {}, {}", args.0, args.1); Ok(()) }); - let print_f64_f64 = Extern::typed_func(|_: &mut tinywasm::Store, args: (f64, f64)| { + let print_f64_f64 = Extern::typed_func(|_ctx: tinywasm::FuncContext, args: (f64, f64)| { log::debug!("print_f64_f64: {}, {}", args.0, args.1); Ok(()) }); @@ -165,11 +163,7 @@ impl TestSuite { test_group.add_result(&format!("Wat({})", i), span.linecol_in(wast), result.map(|_| ())); } - AssertMalformed { - span, - mut module, - message: _, - } => { + AssertMalformed { span, mut module, message: _ } => { let Ok(module) = module.encode() else { test_group.add_result(&format!("AssertMalformed({})", i), span.linecol_in(wast), Ok(())); continue; @@ -189,11 +183,7 @@ impl TestSuite { ); } - AssertInvalid { - span, - mut module, - message: _, - } => { + AssertInvalid { span, mut module, message: _ } => { let res = catch_unwind_silent(move || parse_module_bytes(&module.encode().unwrap())) .map_err(|e| eyre!("failed to parse module (invalid): {:?}", try_downcast_panic(e))) .and_then(|res| res); @@ -303,15 +293,13 @@ impl TestSuite { Invoke(invoke) => { let name = invoke.name; let res: Result, _> = catch_unwind_silent(|| { - let args = invoke - .args - .into_iter() - .map(wastarg2tinywasmvalue) - .collect::>>() - .map_err(|e| { - error!("failed to convert args: {:?}", e); - e - })?; + let args = + invoke.args.into_iter().map(wastarg2tinywasmvalue).collect::>>().map_err( + |e| { + error!("failed to convert args: {:?}", e); + e + }, + )?; exec_fn_instance(last_module.as_ref(), &mut store, invoke.name, &args).map_err(|e| { error!("failed to execute function: {:?}", e); @@ -320,9 +308,7 @@ impl TestSuite { Ok(()) }); - let res = res - .map_err(|e| eyre!("test panicked: {:?}", try_downcast_panic(e))) - .and_then(|r| r); + let res = res.map_err(|e| eyre!("test panicked: {:?}", try_downcast_panic(e))).and_then(|r| r); test_group.add_result(&format!("Invoke({}-{})", name, i), span.linecol_in(wast), res); } @@ -348,15 +334,13 @@ impl TestSuite { let res: Result, _> = catch_unwind_silent(|| { debug!("invoke: {:?}", invoke); - let args = invoke - .args - .into_iter() - .map(wastarg2tinywasmvalue) - .collect::>>() - .map_err(|e| { - error!("failed to convert args: {:?}", e); - e - })?; + let args = + invoke.args.into_iter().map(wastarg2tinywasmvalue).collect::>>().map_err( + |e| { + error!("failed to convert args: {:?}", e); + e + }, + )?; let outcomes = exec_fn_instance(last_module.as_ref(), &mut store, invoke.name, &args).map_err(|e| { @@ -366,14 +350,13 @@ impl TestSuite { debug!("outcomes: {:?}", outcomes); - let expected = results - .into_iter() - .map(wastret2tinywasmvalue) - .collect::>>() - .map_err(|e| { - error!("failed to convert expected results: {:?}", e); - e - })?; + let expected = + results.into_iter().map(wastret2tinywasmvalue).collect::>>().map_err( + |e| { + error!("failed to convert expected results: {:?}", e); + e + }, + )?; debug!("expected: {:?}", expected); @@ -386,26 +369,16 @@ impl TestSuite { )); } - outcomes - .iter() - .zip(expected) - .enumerate() - .try_for_each(|(i, (outcome, exp))| { - (outcome.eq_loose(&exp)) - .then_some(()) - .ok_or_else(|| eyre!(" result {} did not match: {:?} != {:?}", i, outcome, exp)) - }) + outcomes.iter().zip(expected).enumerate().try_for_each(|(i, (outcome, exp))| { + (outcome.eq_loose(&exp)) + .then_some(()) + .ok_or_else(|| eyre!(" result {} did not match: {:?} != {:?}", i, outcome, exp)) + }) }); - let res = res - .map_err(|e| eyre!("test panicked: {:?}", try_downcast_panic(e))) - .and_then(|r| r); + let res = res.map_err(|e| eyre!("test panicked: {:?}", try_downcast_panic(e))).and_then(|r| r); - test_group.add_result( - &format!("AssertReturn({}-{})", invoke_name, i), - span.linecol_in(wast), - res, - ); + test_group.add_result(&format!("AssertReturn({}-{})", invoke_name, i), span.linecol_in(wast), res); } _ => test_group.add_result( &format!("Unknown({})", i), From 2a45ead9e97b845533fc2eb2cd9ee97dba72d02d Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 17:20:38 +0100 Subject: [PATCH 26/52] fix: comments tests Signed-off-by: Henry Gressmann --- crates/tinywasm/src/imports.rs | 30 +++++++++++++------------ crates/tinywasm/src/store.rs | 2 +- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/testsuite/mod.rs | 19 +++++----------- crates/tinywasm/tests/testsuite/run.rs | 25 +++++++++++++++++---- 5 files changed, 45 insertions(+), 33 deletions(-) diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 683f65a..acfcb24 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -246,7 +246,7 @@ impl Imports { pub(crate) fn take( &mut self, - _store: &mut crate::Store, + store: &mut crate::Store, import: &Import, ) -> Option> { let name = ExternName::from(import); @@ -254,19 +254,21 @@ impl Imports { if let Some(v) = self.values.get(&name) { return Some(ResolvedExtern::Extern(v.clone())); } - log::error!("failed to resolve import: {:?}", name); - // TODO: - // if let Some(addr) = self.modules.get(&name.module) { - // let instance = store.get_module_instance(*addr)?; - // let exports = instance.exports(); - - // let export = exports.get_untyped(&import.name)?; - // let addr = match export.kind { - // ExternalKind::Global(g) => ExternVal::Global(), - // }; - - // return Some(ResolvedExtern::Store()); - // } + + if let Some(addr) = self.modules.get(&name.module) { + let instance = store.get_module_instance(*addr)?; + let export_addr = instance.export(&import.name)?; + + // TODO: validate kind and type + match &export_addr { + ExternVal::Global(_) => {} + ExternVal::Table(_) => {} + ExternVal::Mem(_) => {} + ExternVal::Func(_) => {} + } + + return Some(ResolvedExtern::Store(export_addr)); + } None } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index c3a1a6c..70e9ebc 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -44,7 +44,7 @@ impl Store { Self::default() } - pub(crate) fn _get_module_instance(&self, addr: ModuleInstanceAddr) -> Option<&ModuleInstance> { + pub(crate) fn get_module_instance(&self, addr: ModuleInstanceAddr) -> Option<&ModuleInstance> { self.module_instances.get(addr as usize) } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 98a5a76..a460721 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,19982,246,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":81,"failed":18},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":75,"failed":108},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":18,"failed":114},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20065,163,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":84,"failed":15},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":106,"failed":77},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":66,"failed":66},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/testsuite/mod.rs b/crates/tinywasm/tests/testsuite/mod.rs index 36fc727..2019c04 100644 --- a/crates/tinywasm/tests/testsuite/mod.rs +++ b/crates/tinywasm/tests/testsuite/mod.rs @@ -46,9 +46,7 @@ impl TestSuite { if let Err(e) = &test.result { eprintln!( "{} {} failed: {:?}", - link(group_name, &group.file, Some(test.linecol.0 + 1)) - .bold() - .underline(), + link(group_name, &group.file, Some(test.linecol.0 + 1)).bold().underline(), test_name.bold(), e.to_string().bright_red() ); @@ -98,11 +96,7 @@ impl TestSuite { passed += group_passed; failed += group_failed; - groups.push(TestGroupResult { - name: name.to_string(), - passed: group_passed, - failed: group_failed, - }); + groups.push(TestGroupResult { name: name.to_string(), passed: group_passed, failed: group_failed }); } let groups = serde_json::to_string(&groups)?; @@ -134,7 +128,9 @@ impl Debug for TestSuite { writeln!(f, "{}", link(group_name, &group.file, None).bold().underline())?; writeln!(f, " Tests Passed: {}", group_passed.to_string().green())?; - writeln!(f, " Tests Failed: {}", group_failed.to_string().red())?; + if group_failed != 0 { + writeln!(f, " Tests Failed: {}", group_failed.to_string().red())?; + } // for (test_name, test) in &group.tests { // write!(f, " {}: ", test_name.bold())?; @@ -166,10 +162,7 @@ struct TestGroup { impl TestGroup { fn new(file: &str) -> Self { - Self { - tests: IndexMap::new(), - file: file.to_string(), - } + Self { tests: IndexMap::new(), file: file.to_string() } } fn stats(&self) -> (usize, usize) { diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index d41ddca..0ccc44f 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -6,7 +6,7 @@ use eyre::{eyre, Result}; use log::{debug, error, info}; use tinywasm::{Extern, Imports, ModuleInstance}; use tinywasm_types::{MemoryType, ModuleInstanceAddr, TableType, ValType, WasmValue}; -use wast::{lexer::Lexer, parser::ParseBuffer, Wast}; +use wast::{lexer::Lexer, parser::ParseBuffer, QuoteWat, Wast}; impl TestSuite { pub fn run_paths(&mut self, tests: &[&str]) -> Result<()> { @@ -134,13 +134,30 @@ impl TestSuite { test_group.add_result(&format!("Register({})", i), span.linecol_in(wast), Ok(())); } - Wat(mut module) => { + Wat(module) => { // TODO: modules are not properly isolated from each other - tests fail because of this otherwise // store = tinywasm::Store::default(); debug!("got wat module"); let result = catch_unwind_silent(|| { - let m = parse_module_bytes(&module.encode().expect("failed to encode module")) - .expect("failed to parse module bytes"); + let bytes = match module { + QuoteWat::QuoteModule(_, quoted_wat) => { + let wat = quoted_wat + .iter() + .map(|(_, s)| std::str::from_utf8(&s).expect("failed to convert wast to utf8")) + .collect::>() + .join("\n"); + + let lexer = Lexer::new(&wat); + let buf = ParseBuffer::new_with_lexer(lexer).expect("failed to create parse buffer"); + let mut wat_data = wast::parser::parse::(&buf).expect("failed to parse wat"); + wat_data.encode() + } + QuoteWat::Wat(mut wat) => wat.encode(), + _ => unimplemented!("Not supported"), + } + .expect("failed to encode module"); + + let m = parse_module_bytes(&bytes).expect("failed to parse module bytes"); tinywasm::Module::from(m) .instantiate(&mut store, Some(Self::imports(registered_modules.clone()).unwrap())) .map_err(|e| { From 0df1a2cd3b20a0378b0b6853bd116f86c2dee7ff Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 18:06:39 +0100 Subject: [PATCH 27/52] test: add global val tests Signed-off-by: Henry Gressmann --- crates/tinywasm/src/instance.rs | 4 +- crates/tinywasm/src/store.rs | 5 +- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 8 +- crates/tinywasm/tests/testsuite/run.rs | 73 ++++++++++++++++--- 5 files changed, 73 insertions(+), 19 deletions(-) diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index ead3439..c7e5c4a 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -95,8 +95,8 @@ impl ModuleInstance { Ok(instance) } - /// Get the module's exports - pub(crate) fn export(&self, name: &str) -> Option { + /// Get a export by name + pub fn export(&self, name: &str) -> Option { let exports = self.0.exports.iter().find(|e| e.name == name.into())?; let kind = exports.kind.clone(); let addr = match kind { diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 70e9ebc..15b0c2f 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -44,7 +44,8 @@ impl Store { Self::default() } - pub(crate) fn get_module_instance(&self, addr: ModuleInstanceAddr) -> Option<&ModuleInstance> { + /// Get a module instance by the internal id + pub fn get_module_instance(&self, addr: ModuleInstanceAddr) -> Option<&ModuleInstance> { self.module_instances.get(addr as usize) } @@ -348,7 +349,7 @@ impl Store { } /// Get the global at the actual index in the store - pub(crate) fn get_global_val(&self, addr: usize) -> Result { + pub fn get_global_val(&self, addr: usize) -> Result { self.data .globals .get(addr) diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index a460721..4378713 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20065,163,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":84,"failed":15},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":106,"failed":77},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":66,"failed":66},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20068,160,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":84,"failed":15},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":93,"failed":3},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":106,"failed":77},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":68,"failed":64},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 8ab81a8..5d42f8f 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (19982) +v0.3.0-alpha.0 (20068) - - - + + + diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 0ccc44f..1d1502b 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -5,7 +5,7 @@ use super::TestSuite; use eyre::{eyre, Result}; use log::{debug, error, info}; use tinywasm::{Extern, Imports, ModuleInstance}; -use tinywasm_types::{MemoryType, ModuleInstanceAddr, TableType, ValType, WasmValue}; +use tinywasm_types::{ExternVal, MemoryType, ModuleInstanceAddr, TableType, ValType, WasmValue}; use wast::{lexer::Lexer, parser::ParseBuffer, QuoteWat, Wast}; impl TestSuite { @@ -332,9 +332,70 @@ impl TestSuite { AssertReturn { span, exec, results } => { info!("AssertReturn: {:?}", exec); + let expected = + results.into_iter().map(wastret2tinywasmvalue).collect::>>().map_err(|e| { + error!("failed to convert expected results: {:?}", e); + e + })?; + let invoke = match match exec { wast::WastExecute::Wat(_) => Err(eyre!("wat not supported")), - wast::WastExecute::Get { module: _, global: _ } => Err(eyre!("get not supported")), + wast::WastExecute::Get { module: module_id, global } => { + let module = match module_id { + None => last_module.as_ref(), + Some(module_id) => registered_modules + .iter() + .find(|(m, _)| m == module_id.name()) + .map(|(_, addr)| store.get_module_instance(*addr)) + .flatten(), + }; + + let Some(module) = module else { + test_group.add_result( + &format!("AssertReturn(unsupported-{})", i), + span.linecol_in(wast), + Err(eyre!("no module to get global from")), + ); + continue; + }; + + let module_global = match match module.export(global) { + Some(ExternVal::Global(addr)) => { + store.get_global_val(addr as usize).map_err(|_| eyre!("failed to get global")) + } + _ => Err(eyre!("no module to get global from")), + } { + Ok(module_global) => module_global, + Err(err) => { + test_group.add_result( + &format!("AssertReturn(unsupported-{})", i), + span.linecol_in(wast), + Err(eyre!("failed to get global: {:?}", err)), + ); + continue; + } + }; + let expected = expected.get(0).expect("expected global value"); + let module_global = module_global.attach_type(expected.val_type()); + + if !module_global.eq_loose(expected) { + test_group.add_result( + &format!("AssertReturn(unsupported-{})", i), + span.linecol_in(wast), + Err(eyre!("global value did not match: {:?} != {:?}", module_global, expected)), + ); + continue; + } + + test_group.add_result( + &format!("AssertReturn({}-{})", global, i), + span.linecol_in(wast), + Ok(()), + ); + + continue; + // check if module_global matches the expected results + } wast::WastExecute::Invoke(invoke) => Ok(invoke), } { Ok(invoke) => invoke, @@ -367,14 +428,6 @@ impl TestSuite { debug!("outcomes: {:?}", outcomes); - let expected = - results.into_iter().map(wastret2tinywasmvalue).collect::>>().map_err( - |e| { - error!("failed to convert expected results: {:?}", e); - e - }, - )?; - debug!("expected: {:?}", expected); if outcomes.len() != expected.len() { From 5d7f3bca95afb465b12b699df031b3f6139982da Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Mon, 22 Jan 2024 21:56:47 +0100 Subject: [PATCH 28/52] chore: wip imports Signed-off-by: Henry Gressmann --- crates/tinywasm/src/func.rs | 13 ++++++++++-- crates/tinywasm/src/imports.rs | 5 +++-- crates/tinywasm/src/instance.rs | 2 +- crates/tinywasm/src/runtime/executor/mod.rs | 13 ++++++++---- .../tinywasm/src/runtime/stack/value_stack.rs | 18 ++++++++++++----- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/types/src/lib.rs | 20 +++++++++++++++---- 7 files changed, 54 insertions(+), 19 deletions(-) diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 87259f5..93ddbb2 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -167,13 +167,17 @@ macro_rules! impl_from_wasm_value_tuple { fn from_wasm_value_tuple(values: Vec) -> Result { #[allow(unused_variables, unused_mut)] let mut iter = values.into_iter(); + + log::error!("from_wasm_value_tuple: {:?}", iter); + Ok(( $( $T::try_from( iter.next() .ok_or(Error::Other("Not enough values in WasmValue vector".to_string()))? ) - .map_err(|_| Error::Other("Could not convert WasmValue to expected type".to_string()))?, + .map_err(|e| Error::Other(format!("FromWasmValueTuple: Could not convert WasmValue to expected type: {:?}", e, + )))?, )* )) } @@ -188,7 +192,12 @@ macro_rules! impl_from_wasm_value_tuple_single { #[allow(unused_variables, unused_mut)] let mut iter = values.into_iter(); $T::try_from(iter.next().ok_or(Error::Other("Not enough values in WasmValue vector".to_string()))?) - .map_err(|_| Error::Other("Could not convert WasmValue to expected type".to_string())) + .map_err(|e| { + Error::Other(format!( + "FromWasmValueTupleSingle: Could not convert WasmValue to expected type: {:?}", + e + )) + }) } } }; diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index acfcb24..6b60fbd 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -160,11 +160,13 @@ impl Extern { pub fn typed_func(func: impl Fn(FuncContext<'_>, P) -> Result + 'static + Send + Sync) -> Self where P: FromWasmValueTuple + ValTypesFromTuple, - R: IntoWasmValueTuple + ValTypesFromTuple, + R: IntoWasmValueTuple + ValTypesFromTuple + Debug, { let inner_func = move |ctx: FuncContext<'_>, args: &[WasmValue]| -> Result> { + log::error!("args: {:?}", args); let args = P::from_wasm_value_tuple(args.to_vec())?; let result = func(ctx, args)?; + log::error!("result: {:?}", result); Ok(result.into_wasm_value_tuple()) }; @@ -250,7 +252,6 @@ impl Imports { import: &Import, ) -> Option> { let name = ExternName::from(import); - log::error!("provided externs: {:?}", self.values.keys()); if let Some(v) = self.values.get(&name) { return Some(ResolvedExtern::Extern(v.clone())); } diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index c7e5c4a..5465125 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -15,7 +15,7 @@ use crate::{ /// /// See #[derive(Debug, Clone)] -pub struct ModuleInstance(Arc); +pub struct ModuleInstance(pub(crate) Arc); #[allow(dead_code)] #[derive(Debug)] diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 80ad4b4..ab2ab9b 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -7,6 +7,7 @@ use crate::{ CallFrame, Error, FuncContext, LabelArgs, ModuleInstance, Result, Store, Trap, }; use alloc::{string::ToString, vec::Vec}; +use log::info; use tinywasm_types::{ElementKind, Instruction}; mod macros; @@ -127,7 +128,7 @@ fn exec_one( } Call(v) => { - debug!("start call"); + log::info!("start call"); // prepare the call frame let func_idx = module.resolve_func_addr(*v); let func_inst = store.get_func(func_idx as usize)?; @@ -135,17 +136,21 @@ fn exec_one( crate::Function::Wasm(ref f) => f, crate::Function::Host(host_func) => { let func = host_func.func.clone(); + log::info!("Getting params: {:?}", host_func.ty.params); let params = stack.values.pop_params(&host_func.ty.params)?; + log::error!("Calling host function, params: {:?}", params); let res = (func)(FuncContext { store, module }, ¶ms)?; stack.values.extend_from_typed(&res); return Ok(ExecResult::Ok); } }; - let func_ty = module.func_ty(func.ty_addr); + log::info!("wasm call, ty: {:?}", func.ty_addr); + log::info!("tys: {:?}", module.0.types); + let func_ty = func_inst.func.ty(module); - debug!("params: {:?}", func_ty.params); - debug!("stack: {:?}", stack.values); + info!("params: {:?}", func_ty.params); + info!("stack: {:?}", stack.values); let params = stack.values.pop_n_rev(func_ty.params.len())?; let call_frame = CallFrame::new_raw(func_idx as usize, ¶ms, func.locals.to_vec()); diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index 7b4613d..cfd534c 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -30,6 +30,10 @@ impl ValueStack { #[inline] pub(crate) fn extend_from_typed(&mut self, values: &[WasmValue]) { + if values.is_empty() { + return; + } + self.top += values.len(); self.stack.extend(values.iter().map(|v| RawWasmValue::from(*v))); } @@ -82,12 +86,16 @@ impl ValueStack { #[inline] pub(crate) fn pop_params(&mut self, types: &[ValType]) -> Result> { - let n = types.len(); - if self.top < n { - return Err(Error::StackUnderflow); + log::info!("pop_params: types={:?}", types); + log::info!("stack={:?}", self.stack); + + let mut res = Vec::with_capacity(types.len()); + for ty in types.iter() { + let v = self.pop()?; + let v = v.attach_type(*ty); + res.push(v.into()); } - self.top -= n; - let res = self.stack.drain(self.top..).rev().map(|v| v.attach_type(types[n - 1])).collect(); + Ok(res) } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 4378713..6fb3476 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20068,160,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":84,"failed":15},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":93,"failed":3},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":106,"failed":77},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":68,"failed":64},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20069,159,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":84,"failed":15},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":93,"failed":3},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":107,"failed":76},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":68,"failed":64},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index a9cbdcd..96866d3 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -171,7 +171,10 @@ impl TryFrom for i32 { fn try_from(value: WasmValue) -> Result { match value { WasmValue::I32(i) => Ok(i), - _ => Err(()), + _ => { + log::error!("i32: try_from failed: {:?}", value); + Err(()) + } } } } @@ -182,7 +185,10 @@ impl TryFrom for i64 { fn try_from(value: WasmValue) -> Result { match value { WasmValue::I64(i) => Ok(i), - _ => Err(()), + _ => { + log::error!("i64: try_from failed: {:?}", value); + Err(()) + } } } } @@ -193,7 +199,10 @@ impl TryFrom for f32 { fn try_from(value: WasmValue) -> Result { match value { WasmValue::F32(i) => Ok(i), - _ => Err(()), + _ => { + log::error!("f32: try_from failed: {:?}", value); + Err(()) + } } } } @@ -204,7 +213,10 @@ impl TryFrom for f64 { fn try_from(value: WasmValue) -> Result { match value { WasmValue::F64(i) => Ok(i), - _ => Err(()), + _ => { + log::error!("f64: try_from failed: {:?}", value); + Err(()) + } } } } From 1617d7a24fc454130215336b986c0607bec374de Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 23 Jan 2024 13:56:31 +0100 Subject: [PATCH 29/52] core: attach types to functions Signed-off-by: Henry Gressmann --- crates/parser/src/lib.rs | 35 ++++++++++++------- crates/parser/src/module.rs | 28 ++++++--------- crates/tinywasm/src/imports.rs | 12 ++++--- crates/tinywasm/src/instance.rs | 17 +++------ crates/tinywasm/src/runtime/executor/mod.rs | 15 +++----- .../tinywasm/src/runtime/stack/value_stack.rs | 4 +-- crates/tinywasm/src/store.rs | 23 +++++++++--- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/test-wast.rs | 2 +- crates/types/src/lib.rs | 4 +-- 10 files changed, 73 insertions(+), 69 deletions(-) diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 0618683..ae6cc4d 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -20,7 +20,7 @@ mod log { mod conversion; mod error; mod module; -use alloc::vec::Vec; +use alloc::{string::ToString, vec::Vec}; pub use error::*; use module::ModuleReader; use tinywasm_types::WasmFunction; @@ -103,15 +103,26 @@ impl TryFrom for TinyWasmModule { return Err(ParseError::EndNotReached); } - let func_types = reader.func_addrs; + let code_type_addrs = reader.code_type_addrs; + let local_function_count = reader.code.len(); + + if code_type_addrs.len() != local_function_count { + return Err(ParseError::Other("Code and code type address count mismatch".to_string())); + } + let funcs = reader .code .into_iter() - .zip(func_types) - .map(|(f, ty)| WasmFunction { - instructions: f.body, - locals: f.locals, - ty_addr: ty, + .zip(code_type_addrs) + .map(|(f, ty_idx)| { + ( + ty_idx, + WasmFunction { + instructions: f.body, + locals: f.locals, + ty: reader.func_types.get(ty_idx as usize).unwrap().clone(), + }, + ) }) .collect::>(); @@ -119,17 +130,17 @@ impl TryFrom for TinyWasmModule { let table_types = reader.table_types; Ok(TinyWasmModule { - version: reader.version, - start_func: reader.start_func, - func_types: reader.func_types.into_boxed_slice(), funcs: funcs.into_boxed_slice(), - exports: reader.exports.into_boxed_slice(), + func_types: reader.func_types.into_boxed_slice(), globals: globals.into_boxed_slice(), table_types: table_types.into_boxed_slice(), - memory_types: reader.memory_types.into_boxed_slice(), imports: reader.imports.into_boxed_slice(), + version: reader.version, + start_func: reader.start_func, data: reader.data.into_boxed_slice(), + exports: reader.exports.into_boxed_slice(), elements: reader.elements.into_boxed_slice(), + memory_types: reader.memory_types.into_boxed_slice(), }) } } diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs index 660a702..811c51f 100644 --- a/crates/parser/src/module.rs +++ b/crates/parser/src/module.rs @@ -17,7 +17,10 @@ pub struct ModuleReader { pub start_func: Option, pub func_types: Vec, - pub func_addrs: Vec, + + // map from local function index to type index + pub code_type_addrs: Vec, + pub exports: Vec, pub code: Vec, pub globals: Vec, @@ -36,7 +39,7 @@ impl Debug for ModuleReader { f.debug_struct("ModuleReader") .field("version", &self.version) .field("func_types", &self.func_types) - .field("func_addrs", &self.func_addrs) + .field("func_addrs", &self.code_type_addrs) .field("code", &self.code) .field("exports", &self.exports) .field("globals", &self.globals) @@ -88,13 +91,13 @@ impl ModuleReader { .collect::>>()?; } FunctionSection(reader) => { - if !self.func_addrs.is_empty() { + if !self.code_type_addrs.is_empty() { return Err(ParseError::DuplicateSection("Function section".into())); } debug!("Found function section"); validator.function_section(&reader)?; - self.func_addrs = reader.into_iter().map(|f| Ok(f?)).collect::>>()?; + self.code_type_addrs = reader.into_iter().map(|f| Ok(f?)).collect::>>()?; } GlobalSection(reader) => { if !self.globals.is_empty() { @@ -148,9 +151,7 @@ impl ModuleReader { debug!("Found code section entry"); let v = validator.code_section_entry(&function)?; let func_validator = v.into_validator(Default::default()); - - self.code - .push(conversion::convert_module_code(function, func_validator)?); + self.code.push(conversion::convert_module_code(function, func_validator)?); } ImportSection(reader) => { if !self.imports.is_empty() { @@ -168,10 +169,8 @@ impl ModuleReader { debug!("Found export section"); validator.export_section(&reader)?; - self.exports = reader - .into_iter() - .map(|e| conversion::convert_module_export(e?)) - .collect::>>()?; + self.exports = + reader.into_iter().map(|e| conversion::convert_module_export(e?)).collect::>>()?; } End(offset) => { debug!("Reached end of module"); @@ -191,12 +190,7 @@ impl ModuleReader { // validator.tag_section(&tag)?; // } UnknownSection { .. } => return Err(ParseError::UnsupportedSection("Unknown section".into())), - section => { - return Err(ParseError::UnsupportedSection(format!( - "Unsupported section: {:?}", - section - ))) - } + section => return Err(ParseError::UnsupportedSection(format!("Unsupported section: {:?}", section))), }; Ok(()) diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 6b60fbd..a6c07b5 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -25,11 +25,10 @@ pub enum Function { } impl Function { - /// Get the function's type - pub fn ty(&self, module: &crate::ModuleInstance) -> tinywasm_types::FuncType { + pub(crate) fn ty(&self) -> &FuncType { match self { - Self::Host(f) => f.ty.clone(), - Self::Wasm(f) => module.func_ty(f.ty_addr).clone(), + Self::Host(f) => &f.ty, + Self::Wasm(f) => &f.ty, } } } @@ -309,7 +308,10 @@ impl Imports { Extern::Global(g) => store.add_global(g.ty, g.val.into(), idx)?, Extern::Table(t) => store.add_table(t.ty, idx)?, Extern::Memory(m) => store.add_mem(m.ty, idx)?, - Extern::Func(f) => store.add_func(f, idx)?, + Extern::Func(f) => { + let ImportKind::Func(import_type) = import.kind else { unreachable!() }; + store.add_func(f, import_type, idx)? + } }; // store the link diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 5465125..3732832 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -24,6 +24,7 @@ pub(crate) struct ModuleInstanceInner { pub(crate) idx: ModuleInstanceAddr, pub(crate) types: Box<[FuncType]>, + pub(crate) func_addrs: Vec, pub(crate) table_addrs: Vec, pub(crate) mem_addrs: Vec, @@ -59,31 +60,22 @@ impl ModuleInstance { addrs.globals.extend(store.init_globals(data.globals.into(), idx)?); addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?); addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?); - - log::info!("init_mems: {:?}", addrs.mems); addrs.mems.extend(store.init_mems(data.memory_types.into(), idx)?); - log::info!("init_mems2: {:?}", addrs.mems); - log::info!("init_mems g: {:?}", store.data.mems.len()); let elem_addrs = store.init_elems(&addrs.tables, data.elements.into(), idx)?; - log::info!("init_elems: {:?}", addrs.mems); - let data_addrs = store.init_datas(&addrs.mems, data.data.into(), idx)?; - log::info!("init_datas: {:?}", addrs.mems); let instance = ModuleInstanceInner { store_id: store.id(), idx, types: data.func_types, - func_addrs: addrs.funcs, table_addrs: addrs.tables, mem_addrs: addrs.mems, global_addrs: addrs.globals, elem_addrs, data_addrs, - func_start: data.start_func, imports: data.imports, exports: data.exports, @@ -166,7 +158,7 @@ impl ModuleInstance { }; let func_inst = store.get_func(func_addr as usize)?; - let ty = func_inst.func.ty(self); + let ty = func_inst.func.ty(); Ok(FuncHandle { addr: func_addr, module: self.clone(), name: Some(name.to_string()), ty: ty.clone() }) } @@ -206,11 +198,10 @@ impl ModuleInstance { }; let func_addr = self.0.func_addrs.get(func_index as usize).expect("No func addr for start func, this is a bug"); - let func_inst = store.get_func(*func_addr as usize)?; - let ty = func_inst.func.ty(self); + let ty = func_inst.func.ty(); - Ok(Some(FuncHandle { module: self.clone(), addr: *func_addr, ty, name: None })) + Ok(Some(FuncHandle { module: self.clone(), addr: *func_addr, ty: ty.clone(), name: None })) } /// Invoke the start function of the module diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index ab2ab9b..58b1520 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -7,7 +7,6 @@ use crate::{ CallFrame, Error, FuncContext, LabelArgs, ModuleInstance, Result, Store, Trap, }; use alloc::{string::ToString, vec::Vec}; -use log::info; use tinywasm_types::{ElementKind, Instruction}; mod macros; @@ -132,6 +131,7 @@ fn exec_one( // prepare the call frame let func_idx = module.resolve_func_addr(*v); let func_inst = store.get_func(func_idx as usize)?; + let func = match &func_inst.func { crate::Function::Wasm(ref f) => f, crate::Function::Host(host_func) => { @@ -145,13 +145,7 @@ fn exec_one( } }; - log::info!("wasm call, ty: {:?}", func.ty_addr); - log::info!("tys: {:?}", module.0.types); - let func_ty = func_inst.func.ty(module); - - info!("params: {:?}", func_ty.params); - info!("stack: {:?}", stack.values); - let params = stack.values.pop_n_rev(func_ty.params.len())?; + let params = stack.values.pop_n_rev(func.ty.params.len())?; let call_frame = CallFrame::new_raw(func_idx as usize, ¶ms, func.locals.to_vec()); // push the call frame @@ -175,17 +169,18 @@ fn exec_one( // prepare the call frame let func_inst = store.get_func(resolved_func_addr as usize)?; + let func_ty = func_inst.func.ty(); + let func = match &func_inst.func { crate::Function::Wasm(ref f) => f, crate::Function::Host(host_func) => { let func = host_func.func.clone(); - let params = stack.values.pop_params(&host_func.ty.params)?; + let params = stack.values.pop_params(&func_ty.params)?; let res = (func)(FuncContext { store, module }, ¶ms)?; stack.values.extend_from_typed(&res); return Ok(ExecResult::Ok); } }; - let func_ty = module.func_ty(func.ty_addr); if func_ty != call_ty { return Err( diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index cfd534c..db8468c 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -91,9 +91,7 @@ impl ValueStack { let mut res = Vec::with_capacity(types.len()); for ty in types.iter() { - let v = self.pop()?; - let v = v.attach_type(*ty); - res.push(v.into()); + res.push(self.pop()?.attach_type(*ty)); } Ok(res) diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 15b0c2f..c53f5fc 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -110,13 +110,23 @@ impl Store { } /// Add functions to the store, returning their addresses in the store - pub(crate) fn init_funcs(&mut self, funcs: Vec, idx: ModuleInstanceAddr) -> Result> { + pub(crate) fn init_funcs( + &mut self, + funcs: Vec<(u32, WasmFunction)>, + idx: ModuleInstanceAddr, + ) -> Result> { let func_count = self.data.funcs.len(); let mut func_addrs = Vec::with_capacity(func_count); - for (i, func) in funcs.into_iter().enumerate() { - self.data.funcs.push(Rc::new(FunctionInstance { func: Function::Wasm(func), _owner: idx })); + + for (i, (type_idx, func)) in funcs.into_iter().enumerate() { + self.data.funcs.push(Rc::new(FunctionInstance { + func: Function::Wasm(func), + _type_idx: type_idx, + _owner: idx, + })); func_addrs.push((i + func_count) as FuncAddr); } + Ok(func_addrs) } @@ -287,8 +297,8 @@ impl Store { Ok(self.data.mems.len() as MemAddr - 1) } - pub(crate) fn add_func(&mut self, func: Function, idx: ModuleInstanceAddr) -> Result { - self.data.funcs.push(Rc::new(FunctionInstance { func, _owner: idx })); + pub(crate) fn add_func(&mut self, func: Function, type_idx: TypeAddr, idx: ModuleInstanceAddr) -> Result { + self.data.funcs.push(Rc::new(FunctionInstance { func, _type_idx: type_idx, _owner: idx })); Ok(self.data.funcs.len() as FuncAddr - 1) } @@ -372,6 +382,9 @@ impl Store { /// See pub struct FunctionInstance { pub(crate) func: Function, + + // TODO: this is important for call_indirect + pub(crate) _type_idx: TypeAddr, pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 6fb3476..a21f4e4 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20069,159,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":84,"failed":15},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":93,"failed":3},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":107,"failed":76},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":68,"failed":64},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20071,157,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":84,"failed":15},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":93,"failed":3},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":108,"failed":75},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":69,"failed":63},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/test-wast.rs b/crates/tinywasm/tests/test-wast.rs index a0825b0..a50a612 100644 --- a/crates/tinywasm/tests/test-wast.rs +++ b/crates/tinywasm/tests/test-wast.rs @@ -30,7 +30,7 @@ fn main() -> Result<()> { } fn test_wast(wast_file: &str) -> Result<()> { - TestSuite::set_log_level(log::LevelFilter::Info); + TestSuite::set_log_level(log::LevelFilter::Debug); let args = std::env::args().collect::>(); println!("args: {:?}", args); diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 96866d3..87581e1 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -42,7 +42,7 @@ pub struct TinyWasmModule { pub start_func: Option, /// The functions of the WebAssembly module. - pub funcs: Box<[WasmFunction]>, + pub funcs: Box<[(u32, WasmFunction)]>, /// The types of the WebAssembly module. pub func_types: Box<[FuncType]>, @@ -355,9 +355,9 @@ impl FuncType { #[derive(Debug, Clone)] pub struct WasmFunction { - pub ty_addr: TypeAddr, pub instructions: Box<[Instruction]>, pub locals: Box<[ValType]>, + pub ty: FuncType, } /// A WebAssembly Module Export From ba42c614ec658ff950d45f2e1bae0efaf42d22a6 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 23 Jan 2024 14:47:11 +0100 Subject: [PATCH 30/52] chore: improve testsuite Signed-off-by: Henry Gressmann --- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 8 +- crates/tinywasm/tests/testsuite/run.rs | 192 ++++++++++-------- crates/tinywasm/tests/testsuite/util.rs | 20 +- 4 files changed, 127 insertions(+), 95 deletions(-) diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index a21f4e4..6e46b59 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20071,157,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":84,"failed":15},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":93,"failed":3},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":108,"failed":75},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":69,"failed":63},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20084,144,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":83,"failed":16},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":94,"failed":2},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":105,"failed":78},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":85,"failed":47},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 5d42f8f..809c464 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20068) +v0.3.0-alpha.0 (20084) - - - + + + diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 1d1502b..a48c271 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -1,5 +1,5 @@ use crate::testsuite::util::*; -use std::borrow::Cow; +use std::{borrow::Cow, collections::HashMap}; use super::TestSuite; use eyre::{eyre, Result}; @@ -8,6 +8,61 @@ use tinywasm::{Extern, Imports, ModuleInstance}; use tinywasm_types::{ExternVal, MemoryType, ModuleInstanceAddr, TableType, ValType, WasmValue}; use wast::{lexer::Lexer, parser::ParseBuffer, QuoteWat, Wast}; +struct RegisteredModules { + modules: HashMap, + last_module: Option<(ModuleInstanceAddr, Option)>, +} + +impl RegisteredModules { + fn modules(&self) -> &HashMap { + &self.modules + } + + fn update_last_module(&mut self, addr: ModuleInstanceAddr, name: Option) { + self.last_module = Some((addr, name)); + } + fn register(&mut self, name: String, addr: ModuleInstanceAddr) { + log::debug!("registering module: {}", name); + self.modules.insert(name.clone(), addr); + self.last_module = Some((addr, Some(name))); + } + + fn get_idx(&self, module_id: Option>) -> Option<&ModuleInstanceAddr> { + match module_id { + Some(module) => { + log::debug!("getting module: {}", module.name()); + + if let Some(addr) = self.modules.get(module.name()) { + return Some(addr); + } + + let Some((last, Some(name))) = self.last_module.as_ref() else { + return None; + }; + + match module.name() == name { + true => Some(&last), + false => None, + } + } + None => self.last_module.as_ref().map(|(addr, _)| addr), + } + } + + fn get<'a>( + &self, + module_id: Option>, + store: &'a tinywasm::Store, + ) -> Option<&'a ModuleInstance> { + let addr = self.get_idx(module_id)?; + store.get_module_instance(*addr) + } + + fn last<'a>(&self, store: &'a tinywasm::Store) -> Option<&'a ModuleInstance> { + store.get_module_instance(self.last_module.as_ref()?.0) + } +} + impl TestSuite { pub fn run_paths(&mut self, tests: &[&str]) -> Result<()> { tests.iter().for_each(|group| { @@ -19,7 +74,7 @@ impl TestSuite { Ok(()) } - fn imports(registered_modules: Vec<(String, ModuleInstanceAddr)>) -> Result { + fn imports(modules: &HashMap) -> Result { let mut imports = Imports::new(); let table = @@ -75,9 +130,9 @@ impl TestSuite { .define("spectest", "print_i32_f32", print_i32_f32)? .define("spectest", "print_f64_f64", print_f64_f64)?; - for (name, addr) in registered_modules { + for (name, addr) in modules { log::debug!("registering module: {}", name); - imports.link_module(&name, addr)?; + imports.link_module(&name, *addr)?; } Ok(imports) @@ -111,8 +166,7 @@ impl TestSuite { let wast_data = wast::parser::parse::(&buf).expect("failed to parse wat"); let mut store = tinywasm::Store::default(); - let mut registered_modules = Vec::new(); - let mut last_module: Option = None; + let mut registered_modules = RegisteredModules { modules: HashMap::new(), last_module: None }; println!("running {} tests for group: {}", wast_data.directives.len(), group_name); for (i, directive) in wast_data.directives.into_iter().enumerate() { @@ -121,7 +175,7 @@ impl TestSuite { match directive { Register { span, name, .. } => { - let Some(last) = &last_module else { + let Some(last) = registered_modules.last(&store) else { test_group.add_result( &format!("Register({})", i), span.linecol_in(wast), @@ -129,8 +183,7 @@ impl TestSuite { ); continue; }; - - registered_modules.push((name.to_string(), last.id())); + registered_modules.register(name.to_string(), last.id()); test_group.add_result(&format!("Register({})", i), span.linecol_in(wast), Ok(())); } @@ -139,7 +192,7 @@ impl TestSuite { // store = tinywasm::Store::default(); debug!("got wat module"); let result = catch_unwind_silent(|| { - let bytes = match module { + let (name, bytes) = match module { QuoteWat::QuoteModule(_, quoted_wat) => { let wat = quoted_wat .iter() @@ -150,32 +203,34 @@ impl TestSuite { let lexer = Lexer::new(&wat); let buf = ParseBuffer::new_with_lexer(lexer).expect("failed to create parse buffer"); let mut wat_data = wast::parser::parse::(&buf).expect("failed to parse wat"); - wat_data.encode() + (None, wat_data.encode().expect("failed to encode module")) + } + QuoteWat::Wat(mut wat) => { + let wast::Wat::Module(ref module) = wat else { + unimplemented!("Not supported"); + }; + ( + module.id.map(|id| id.name().to_string()), + wat.encode().expect("failed to encode module"), + ) } - QuoteWat::Wat(mut wat) => wat.encode(), _ => unimplemented!("Not supported"), - } - .expect("failed to encode module"); + }; let m = parse_module_bytes(&bytes).expect("failed to parse module bytes"); - tinywasm::Module::from(m) - .instantiate(&mut store, Some(Self::imports(registered_modules.clone()).unwrap())) - .map_err(|e| { - println!("failed to instantiate module: {:?}", e); - e - }) - .expect("failed to instantiate module") + + let module_instance = tinywasm::Module::from(m) + .instantiate(&mut store, Some(Self::imports(registered_modules.modules()).unwrap())) + .expect("failed to instantiate module"); + + (name, module_instance) }) .map_err(|e| eyre!("failed to parse wat module: {:?}", try_downcast_panic(e))); match &result { - Err(_) => last_module = None, - Ok(m) => last_module = Some(m.clone()), - } - - if let Err(err) = &result { - debug!("failed to parse module: {:?}", err) - } + Err(err) => debug!("failed to parse module: {:?}", err), + Ok((name, module)) => registered_modules.update_last_module(module.id(), name.clone()), + }; test_group.add_result(&format!("Wat({})", i), span.linecol_in(wast), result.map(|_| ())); } @@ -216,17 +271,10 @@ impl TestSuite { } AssertExhaustion { call, message, span } => { - let module = last_module.as_ref(); - let name = call.name; - - let args = call - .args - .into_iter() - .map(wastarg2tinywasmvalue) - .collect::>>() - .expect("failed to convert args"); - - let res = catch_unwind_silent(|| exec_fn_instance(module, &mut store, name, &args).map(|_| ())); + let module = registered_modules.get_idx(call.module); + let args = convert_wastargs(call.args).expect("failed to convert args"); + let res = + catch_unwind_silent(|| exec_fn_instance(module, &mut store, call.name, &args).map(|_| ())); let Ok(Err(tinywasm::Error::Trap(trap))) = res else { test_group.add_result( @@ -251,29 +299,26 @@ impl TestSuite { AssertTrap { exec, message, span } => { let res: Result, _> = catch_unwind_silent(|| { - let (module, name, args) = match exec { + let invoke = match exec { wast::WastExecute::Wat(mut wat) => { let module = parse_module_bytes(&wat.encode().expect("failed to encode module")) .expect("failed to parse module"); let module = tinywasm::Module::from(module); module.instantiate( &mut store, - Some(Self::imports(registered_modules.clone()).unwrap()), + Some(Self::imports(registered_modules.modules()).unwrap()), )?; return Ok(()); } wast::WastExecute::Get { module: _, global: _ } => { panic!("get not supported"); } - wast::WastExecute::Invoke(invoke) => (last_module.as_ref(), invoke.name, invoke.args), + wast::WastExecute::Invoke(invoke) => invoke, }; - let args = args - .into_iter() - .map(wastarg2tinywasmvalue) - .collect::>>() - .expect("failed to convert args"); - exec_fn_instance(module, &mut store, name, &args).map(|_| ()) + let module = registered_modules.get_idx(invoke.module); + let args = convert_wastargs(invoke.args).expect("failed to convert args"); + exec_fn_instance(module, &mut store, invoke.name, &args).map(|_| ()) }); match res { @@ -309,16 +354,11 @@ impl TestSuite { Invoke(invoke) => { let name = invoke.name; + let res: Result, _> = catch_unwind_silent(|| { - let args = - invoke.args.into_iter().map(wastarg2tinywasmvalue).collect::>>().map_err( - |e| { - error!("failed to convert args: {:?}", e); - e - }, - )?; - - exec_fn_instance(last_module.as_ref(), &mut store, invoke.name, &args).map_err(|e| { + let args = convert_wastargs(invoke.args)?; + let module = registered_modules.get_idx(invoke.module); + exec_fn_instance(module, &mut store, invoke.name, &args).map_err(|e| { error!("failed to execute function: {:?}", e); e })?; @@ -326,30 +366,17 @@ impl TestSuite { }); let res = res.map_err(|e| eyre!("test panicked: {:?}", try_downcast_panic(e))).and_then(|r| r); - test_group.add_result(&format!("Invoke({}-{})", name, i), span.linecol_in(wast), res); } AssertReturn { span, exec, results } => { info!("AssertReturn: {:?}", exec); - let expected = - results.into_iter().map(wastret2tinywasmvalue).collect::>>().map_err(|e| { - error!("failed to convert expected results: {:?}", e); - e - })?; + let expected = convert_wastret(results)?; let invoke = match match exec { wast::WastExecute::Wat(_) => Err(eyre!("wat not supported")), wast::WastExecute::Get { module: module_id, global } => { - let module = match module_id { - None => last_module.as_ref(), - Some(module_id) => registered_modules - .iter() - .find(|(m, _)| m == module_id.name()) - .map(|(_, addr)| store.get_module_instance(*addr)) - .flatten(), - }; - + let module = registered_modules.get(module_id, &store); let Some(module) = module else { test_group.add_result( &format!("AssertReturn(unsupported-{})", i), @@ -408,23 +435,16 @@ impl TestSuite { continue; } }; - let invoke_name = invoke.name; + let invoke_name = invoke.name; let res: Result, _> = catch_unwind_silent(|| { debug!("invoke: {:?}", invoke); - let args = - invoke.args.into_iter().map(wastarg2tinywasmvalue).collect::>>().map_err( - |e| { - error!("failed to convert args: {:?}", e); - e - }, - )?; - - let outcomes = - exec_fn_instance(last_module.as_ref(), &mut store, invoke.name, &args).map_err(|e| { - error!("failed to execute function: {:?}", e); - e - })?; + let args = convert_wastargs(invoke.args)?; + let module = registered_modules.get_idx(invoke.module); + let outcomes = exec_fn_instance(module, &mut store, invoke.name, &args).map_err(|e| { + error!("failed to execute function: {:?}", e); + e + })?; debug!("outcomes: {:?}", outcomes); diff --git a/crates/tinywasm/tests/testsuite/util.rs b/crates/tinywasm/tests/testsuite/util.rs index bb134d2..a3bb1a1 100644 --- a/crates/tinywasm/tests/testsuite/util.rs +++ b/crates/tinywasm/tests/testsuite/util.rs @@ -1,7 +1,7 @@ use std::panic::{self, AssertUnwindSafe}; use eyre::{eyre, Result}; -use tinywasm_types::{TinyWasmModule, WasmValue}; +use tinywasm_types::{ModuleInstanceAddr, TinyWasmModule, WasmValue}; pub fn try_downcast_panic(panic: Box) -> String { let info = panic.downcast_ref::().or(None).map(|p| p.to_string()).clone(); @@ -12,7 +12,7 @@ pub fn try_downcast_panic(panic: Box) -> String { } pub fn exec_fn_instance( - instance: Option<&tinywasm::ModuleInstance>, + instance: Option<&ModuleInstanceAddr>, store: &mut tinywasm::Store, name: &str, args: &[tinywasm_types::WasmValue], @@ -21,6 +21,10 @@ pub fn exec_fn_instance( return Err(tinywasm::Error::Other("no instance found".to_string())); }; + let Some(instance) = store.get_module_instance(*instance) else { + return Err(tinywasm::Error::Other("no instance found".to_string())); + }; + let func = instance.exported_func_by_name(store, name)?; func.call(store, args) } @@ -54,7 +58,15 @@ pub fn parse_module_bytes(bytes: &[u8]) -> Result { Ok(parser.parse_module_bytes(bytes)?) } -pub fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result { +pub fn convert_wastargs(args: Vec) -> Result> { + args.into_iter().map(|a| wastarg2tinywasmvalue(a)).collect() +} + +pub fn convert_wastret(args: Vec) -> Result> { + args.into_iter().map(|a| wastret2tinywasmvalue(a)).collect() +} + +fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result { let wast::WastArg::Core(arg) = arg else { return Err(eyre!("unsupported arg type: Component")); }; @@ -75,7 +87,7 @@ pub fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result Result { +fn wastret2tinywasmvalue(arg: wast::WastRet) -> Result { let wast::WastRet::Core(arg) = arg else { return Err(eyre!("unsupported arg type")); }; From 4c1386b9ae8c0900ce052e69a6411041ecdbef2e Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 23 Jan 2024 15:13:52 +0100 Subject: [PATCH 31/52] chore: switch module instance when switching call stack Signed-off-by: Henry Gressmann --- crates/tinywasm/src/func.rs | 2 +- crates/tinywasm/src/runtime/executor/mod.rs | 14 ++++++++--- .../tinywasm/src/runtime/stack/call_stack.rs | 25 ++++++++++++++++--- .../tinywasm/src/runtime/stack/value_stack.rs | 2 -- crates/tinywasm/tests/generated/mvp.csv | 2 +- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 93ddbb2..9f9d95a 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -63,7 +63,7 @@ impl FuncHandle { // 6. Let f be the dummy frame debug!("locals: {:?}", wasm_func.locals); - let call_frame = CallFrame::new(self.addr as usize, params, wasm_func.locals.to_vec()); + let call_frame = CallFrame::new(self.addr as usize, params, wasm_func.locals.to_vec(), self.module.id()); // 7. Push the frame f to the call stack // & 8. Push the values to the stack (Not needed since the call frame owns the values) diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 58b1520..5efed53 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -28,16 +28,23 @@ impl DefaultRuntime { let mut wasm_func = func_inst.assert_wasm().expect("exec expected wasm function"); let mut instrs = &wasm_func.instructions; + let mut current_module = module; + // TODO: we might be able to index into the instructions directly // since the instruction pointer should always be in bounds while let Some(instr) = instrs.get(cf.instr_ptr) { - match exec_one(&mut cf, instr, instrs, stack, store, &module)? { + match exec_one(&mut cf, instr, instrs, stack, store, ¤t_module)? { // Continue execution at the new top of the call stack ExecResult::Call => { cf = stack.call_stack.pop()?; func_inst = store.get_func(cf.func_ptr)?.clone(); wasm_func = func_inst.assert_wasm().expect("call expected wasm function"); instrs = &wasm_func.instructions; + + if cf.module != current_module.id() { + current_module = store.get_module_instance(cf.module).unwrap().clone() + } + continue; } @@ -146,7 +153,7 @@ fn exec_one( }; let params = stack.values.pop_n_rev(func.ty.params.len())?; - let call_frame = CallFrame::new_raw(func_idx as usize, ¶ms, func.locals.to_vec()); + let call_frame = CallFrame::new_raw(func_idx as usize, ¶ms, func.locals.to_vec(), func_inst._owner); // push the call frame cf.instr_ptr += 1; // skip the call instruction @@ -189,7 +196,8 @@ fn exec_one( } let params = stack.values.pop_n_rev(func_ty.params.len())?; - let call_frame = CallFrame::new_raw(resolved_func_addr as usize, ¶ms, func.locals.to_vec()); + let call_frame = + CallFrame::new_raw(resolved_func_addr as usize, ¶ms, func.locals.to_vec(), func_inst._owner); // push the call frame cf.instr_ptr += 1; // skip the call instruction diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index 6eb72b5..b1c4f67 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -1,6 +1,6 @@ use crate::{runtime::RawWasmValue, BlockType, Error, LabelFrame, Result, Trap}; use alloc::{boxed::Box, vec::Vec}; -use tinywasm_types::{ValType, WasmValue}; +use tinywasm_types::{ModuleInstanceAddr, ValType, WasmValue}; use super::blocks::Labels; @@ -52,6 +52,7 @@ impl CallStack { #[derive(Debug, Clone)] pub(crate) struct CallFrame { + pub(crate) module: ModuleInstanceAddr, pub(crate) instr_ptr: usize, pub(crate) func_ptr: usize, @@ -107,7 +108,12 @@ impl CallFrame { Some(()) } - pub(crate) fn new_raw(func_ptr: usize, params: &[RawWasmValue], local_types: Vec) -> Self { + pub(crate) fn new_raw( + func_ptr: usize, + params: &[RawWasmValue], + local_types: Vec, + module: ModuleInstanceAddr, + ) -> Self { let mut locals = Vec::with_capacity(local_types.len() + params.len()); locals.extend(params.iter().cloned()); locals.extend(local_types.iter().map(|_| RawWasmValue::default())); @@ -118,11 +124,22 @@ impl CallFrame { local_count: locals.len(), locals: locals.into_boxed_slice(), labels: Labels::default(), + module, } } - pub(crate) fn new(func_ptr: usize, params: &[WasmValue], local_types: Vec) -> Self { - CallFrame::new_raw(func_ptr, ¶ms.iter().map(|v| RawWasmValue::from(*v)).collect::>(), local_types) + pub(crate) fn new( + func_ptr: usize, + params: &[WasmValue], + local_types: Vec, + module: ModuleInstanceAddr, + ) -> Self { + CallFrame::new_raw( + func_ptr, + ¶ms.iter().map(|v| RawWasmValue::from(*v)).collect::>(), + local_types, + module, + ) } #[inline] diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index db8468c..e4467da 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -10,8 +10,6 @@ pub(crate) const STACK_SIZE: usize = 1024; #[derive(Debug)] pub(crate) struct ValueStack { stack: Vec, - - // TODO: don't pop the stack, just keep track of the top for better performance top: usize, } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 6e46b59..9b93091 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20084,144,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":83,"failed":16},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":94,"failed":2},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":105,"failed":78},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":85,"failed":47},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20087,141,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":83,"failed":16},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":94,"failed":2},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":105,"failed":78},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":88,"failed":44},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] From 3e71f86ce9bd12d2b3f7db8c7141e5c62785098c Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 23 Jan 2024 15:39:48 +0100 Subject: [PATCH 32/52] chore: refactor module instances, fix named module tests Signed-off-by: Henry Gressmann --- crates/tinywasm/src/instance.rs | 34 +++++++++++-------- crates/tinywasm/src/runtime/executor/mod.rs | 6 ++-- crates/tinywasm/src/store.rs | 13 ++++--- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 6 ++-- crates/tinywasm/tests/testsuite/run.rs | 31 ++++++++++------- 6 files changed, 53 insertions(+), 39 deletions(-) diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 3732832..38cb42a 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -1,4 +1,4 @@ -use alloc::{boxed::Box, format, string::ToString, sync::Arc, vec::Vec}; +use alloc::{boxed::Box, format, string::ToString, sync::Arc}; use tinywasm_types::{ DataAddr, ElemAddr, Export, ExternVal, ExternalKind, FuncAddr, FuncType, GlobalAddr, Import, MemAddr, ModuleInstanceAddr, TableAddr, @@ -11,11 +11,11 @@ use crate::{ /// A WebAssembly Module Instance /// -/// Addrs are indices into the store's data structures. +/// Backed by an Arc, so cloning is cheap /// /// See #[derive(Debug, Clone)] -pub struct ModuleInstance(pub(crate) Arc); +pub struct ModuleInstance(Arc); #[allow(dead_code)] #[derive(Debug)] @@ -25,12 +25,12 @@ pub(crate) struct ModuleInstanceInner { pub(crate) types: Box<[FuncType]>, - pub(crate) func_addrs: Vec, - pub(crate) table_addrs: Vec, - pub(crate) mem_addrs: Vec, - pub(crate) global_addrs: Vec, - pub(crate) elem_addrs: Vec, - pub(crate) data_addrs: Vec, + pub(crate) func_addrs: Box<[FuncAddr]>, + pub(crate) table_addrs: Box<[TableAddr]>, + pub(crate) mem_addrs: Box<[MemAddr]>, + pub(crate) global_addrs: Box<[GlobalAddr]>, + pub(crate) elem_addrs: Box<[ElemAddr]>, + pub(crate) data_addrs: Box<[DataAddr]>, pub(crate) func_start: Option, pub(crate) imports: Box<[Import]>, @@ -38,6 +38,11 @@ pub(crate) struct ModuleInstanceInner { } impl ModuleInstance { + // drop the module instance reference and swap it with another one + pub(crate) fn swap(&mut self, other: Self) { + self.0 = other.0; + } + /// Get the module instance's address pub fn id(&self) -> ModuleInstanceAddr { self.0.idx @@ -57,6 +62,7 @@ impl ModuleInstance { let mut addrs = imports.link(store, &module, idx)?; let data = module.data; + // TODO: check if the compiler correctly optimizes this to prevent wasted allocations addrs.globals.extend(store.init_globals(data.globals.into(), idx)?); addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?); addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?); @@ -70,12 +76,12 @@ impl ModuleInstance { idx, types: data.func_types, - func_addrs: addrs.funcs, - table_addrs: addrs.tables, - mem_addrs: addrs.mems, - global_addrs: addrs.globals, + func_addrs: addrs.funcs.into_boxed_slice(), + table_addrs: addrs.tables.into_boxed_slice(), + mem_addrs: addrs.mems.into_boxed_slice(), + global_addrs: addrs.globals.into_boxed_slice(), elem_addrs, - data_addrs, + data_addrs: data_addrs, func_start: data.start_func, imports: data.imports, exports: data.exports, diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 5efed53..3420dda 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -30,8 +30,6 @@ impl DefaultRuntime { let mut current_module = module; - // TODO: we might be able to index into the instructions directly - // since the instruction pointer should always be in bounds while let Some(instr) = instrs.get(cf.instr_ptr) { match exec_one(&mut cf, instr, instrs, stack, store, ¤t_module)? { // Continue execution at the new top of the call stack @@ -42,7 +40,7 @@ impl DefaultRuntime { instrs = &wasm_func.instructions; if cf.module != current_module.id() { - current_module = store.get_module_instance(cf.module).unwrap().clone() + current_module.swap(store.get_module_instance(cf.module).unwrap().clone()); } continue; @@ -168,6 +166,8 @@ fn exec_one( let table_idx = module.resolve_table_addr(*table_addr); let table = store.get_table(table_idx as usize)?; + // TODO: currently, the type resolution is subtlely broken for imported functions + let call_ty = module.func_ty(*type_addr); let func_idx = stack.values.pop_t::()?; diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index c53f5fc..5b4c696 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -3,7 +3,7 @@ use core::{ sync::atomic::{AtomicUsize, Ordering}, }; -use alloc::{format, rc::Rc, string::ToString, vec, vec::Vec}; +use alloc::{boxed::Box, format, rc::Rc, string::ToString, vec, vec::Vec}; use tinywasm_types::*; use crate::{ @@ -180,7 +180,7 @@ impl Store { table_addrs: &[TableAddr], elems: Vec, idx: ModuleInstanceAddr, - ) -> Result> { + ) -> Result> { let elem_count = self.data.elems.len(); let mut elem_addrs = Vec::with_capacity(elem_count); for (i, elem) in elems.into_iter().enumerate() { @@ -232,7 +232,8 @@ impl Store { elem_addrs.push((i + elem_count) as Addr); } - Ok(elem_addrs) + // this should be optimized out by the compiler + Ok(elem_addrs.into_boxed_slice()) } /// Add data to the store, returning their addresses in the store @@ -241,7 +242,7 @@ impl Store { mem_addrs: &[MemAddr], datas: Vec, idx: ModuleInstanceAddr, - ) -> Result> { + ) -> Result> { let data_count = self.data.datas.len(); let mut data_addrs = Vec::with_capacity(data_count); for (i, data) in datas.into_iter().enumerate() { @@ -276,7 +277,9 @@ impl Store { self.data.datas.push(DataInstance::new(data.data.to_vec(), idx)); data_addrs.push((i + data_count) as Addr); } - Ok(data_addrs) + + // this should be optimized out by the compiler + Ok(data_addrs.into_boxed_slice()) } pub(crate) fn add_global(&mut self, ty: GlobalType, value: RawWasmValue, idx: ModuleInstanceAddr) -> Result { diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 9b93091..3c3efcb 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20087,141,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":83,"failed":16},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":94,"failed":2},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":105,"failed":78},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":88,"failed":44},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20100,128,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":86,"failed":13},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":108,"failed":75},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":93,"failed":39},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 809c464..86912c5 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20084) +v0.3.0-alpha.0 (20087) + - - + diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index a48c271..6f719f9 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -8,9 +8,12 @@ use tinywasm::{Extern, Imports, ModuleInstance}; use tinywasm_types::{ExternVal, MemoryType, ModuleInstanceAddr, TableType, ValType, WasmValue}; use wast::{lexer::Lexer, parser::ParseBuffer, QuoteWat, Wast}; +#[derive(Default)] struct RegisteredModules { modules: HashMap, - last_module: Option<(ModuleInstanceAddr, Option)>, + + named_modules: HashMap, + last_module: Option, } impl RegisteredModules { @@ -19,12 +22,17 @@ impl RegisteredModules { } fn update_last_module(&mut self, addr: ModuleInstanceAddr, name: Option) { - self.last_module = Some((addr, name)); + self.last_module = Some(addr); + if let Some(name) = name { + self.named_modules.insert(name, addr); + } } fn register(&mut self, name: String, addr: ModuleInstanceAddr) { log::debug!("registering module: {}", name); self.modules.insert(name.clone(), addr); - self.last_module = Some((addr, Some(name))); + + self.last_module = Some(addr); + self.named_modules.insert(name, addr); } fn get_idx(&self, module_id: Option>) -> Option<&ModuleInstanceAddr> { @@ -36,16 +44,13 @@ impl RegisteredModules { return Some(addr); } - let Some((last, Some(name))) = self.last_module.as_ref() else { - return None; - }; - - match module.name() == name { - true => Some(&last), - false => None, + if let Some(addr) = self.named_modules.get(module.name()) { + return Some(addr); } + + None } - None => self.last_module.as_ref().map(|(addr, _)| addr), + None => self.last_module.as_ref(), } } @@ -59,7 +64,7 @@ impl RegisteredModules { } fn last<'a>(&self, store: &'a tinywasm::Store) -> Option<&'a ModuleInstance> { - store.get_module_instance(self.last_module.as_ref()?.0) + store.get_module_instance(*self.last_module.as_ref()?) } } @@ -166,7 +171,7 @@ impl TestSuite { let wast_data = wast::parser::parse::(&buf).expect("failed to parse wat"); let mut store = tinywasm::Store::default(); - let mut registered_modules = RegisteredModules { modules: HashMap::new(), last_module: None }; + let mut registered_modules = RegisteredModules::default(); println!("running {} tests for group: {}", wast_data.directives.len(), group_name); for (i, directive) in wast_data.directives.into_iter().enumerate() { From 52eda3e7e9ecc62776888aa5d3aeef95660dff8d Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 23 Jan 2024 18:23:31 +0100 Subject: [PATCH 33/52] feat: uninitialized elems Signed-off-by: Henry Gressmann --- crates/parser/src/conversion.rs | 9 +-- crates/tinywasm/src/imports.rs | 8 +-- crates/tinywasm/src/instance.rs | 8 +-- crates/tinywasm/src/store.rs | 58 ++++++++++--------- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 6 +- crates/types/src/instructions.rs | 48 +++++++-------- 7 files changed, 71 insertions(+), 68 deletions(-) diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index 4f79a4a..1448d59 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -1,9 +1,6 @@ use alloc::{boxed::Box, format, string::ToString, vec::Vec}; use log::debug; -use tinywasm_types::{ - BlockArgs, ConstInstruction, ElementItem, Export, ExternalKind, FuncType, Global, GlobalType, Import, ImportKind, - Instruction, MemArg, MemoryArch, MemoryType, TableType, ValType, -}; +use tinywasm_types::*; use wasmparser::{FuncValidator, OperatorsReader, ValidatorResources}; use crate::{module::CodeSection, Result}; @@ -210,8 +207,8 @@ pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> ValType { } } -pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemArg { - MemArg { offset: memarg.offset, align: memarg.align, align_max: memarg.max_align, mem_addr: memarg.memory } +pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemoryArg { + MemoryArg { offset: memarg.offset, align: memarg.align, align_max: memarg.max_align, mem_addr: memarg.memory } } pub(crate) fn process_const_operators(ops: OperatorsReader) -> Result { diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index a6c07b5..c557069 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -215,13 +215,13 @@ pub(crate) enum ResolvedExtern { pub(crate) struct ResolvedImports { pub(crate) globals: Vec, pub(crate) tables: Vec, - pub(crate) mems: Vec, + pub(crate) memories: Vec, pub(crate) funcs: Vec, } impl ResolvedImports { pub(crate) fn new() -> Self { - Self { globals: Vec::new(), tables: Vec::new(), mems: Vec::new(), funcs: Vec::new() } + Self { globals: Vec::new(), tables: Vec::new(), memories: Vec::new(), funcs: Vec::new() } } } @@ -318,7 +318,7 @@ impl Imports { match &kind { ExternalKind::Global => imports.globals.push(addr), ExternalKind::Table => imports.tables.push(addr), - ExternalKind::Memory => imports.mems.push(addr), + ExternalKind::Memory => imports.memories.push(addr), ExternalKind::Func => imports.funcs.push(addr), } } @@ -338,7 +338,7 @@ impl Imports { match val { ExternVal::Global(g) => imports.globals.push(g), ExternVal::Table(t) => imports.tables.push(t), - ExternVal::Mem(m) => imports.mems.push(m), + ExternVal::Mem(m) => imports.memories.push(m), ExternVal::Func(f) => imports.funcs.push(f), } } diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 38cb42a..11deedc 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -66,10 +66,10 @@ impl ModuleInstance { addrs.globals.extend(store.init_globals(data.globals.into(), idx)?); addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?); addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?); - addrs.mems.extend(store.init_mems(data.memory_types.into(), idx)?); + addrs.memories.extend(store.init_memories(data.memory_types.into(), idx)?); - let elem_addrs = store.init_elems(&addrs.tables, data.elements.into(), idx)?; - let data_addrs = store.init_datas(&addrs.mems, data.data.into(), idx)?; + let elem_addrs = store.init_elements(&addrs.tables, data.elements.into(), idx)?; + let data_addrs = store.init_datas(&addrs.memories, data.data.into(), idx)?; let instance = ModuleInstanceInner { store_id: store.id(), @@ -78,7 +78,7 @@ impl ModuleInstance { types: data.func_types, func_addrs: addrs.funcs.into_boxed_slice(), table_addrs: addrs.tables.into_boxed_slice(), - mem_addrs: addrs.mems.into_boxed_slice(), + mem_addrs: addrs.memories.into_boxed_slice(), global_addrs: addrs.globals.into_boxed_slice(), elem_addrs, data_addrs: data_addrs, diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 5b4c696..730dbd7 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -86,9 +86,9 @@ impl Default for Store { pub(crate) struct StoreData { pub(crate) funcs: Vec>, pub(crate) tables: Vec>>, - pub(crate) mems: Vec>>, + pub(crate) memories: Vec>>, pub(crate) globals: Vec>>, - pub(crate) elems: Vec, + pub(crate) elements: Vec, pub(crate) datas: Vec, } @@ -142,15 +142,15 @@ impl Store { } /// Add memories to the store, returning their addresses in the store - pub(crate) fn init_mems(&mut self, mems: Vec, idx: ModuleInstanceAddr) -> Result> { - let mem_count = self.data.mems.len(); + pub(crate) fn init_memories(&mut self, memories: Vec, idx: ModuleInstanceAddr) -> Result> { + let mem_count = self.data.memories.len(); let mut mem_addrs = Vec::with_capacity(mem_count); - for (i, mem) in mems.into_iter().enumerate() { + for (i, mem) in memories.into_iter().enumerate() { if let MemoryArch::I64 = mem.arch { return Err(Error::UnsupportedFeature("64-bit memories".to_string())); } log::info!("adding memory: {:?}", mem); - self.data.mems.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); + self.data.memories.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); mem_addrs.push((i + mem_count) as MemAddr); } @@ -175,16 +175,16 @@ impl Store { /// Add elements to the store, returning their addresses in the store /// Should be called after the tables have been added - pub(crate) fn init_elems( + pub(crate) fn init_elements( &mut self, table_addrs: &[TableAddr], - elems: Vec, + elements: Vec, idx: ModuleInstanceAddr, ) -> Result> { - let elem_count = self.data.elems.len(); + let elem_count = self.data.elements.len(); let mut elem_addrs = Vec::with_capacity(elem_count); - for (i, elem) in elems.into_iter().enumerate() { - let init = elem + for (i, element) in elements.into_iter().enumerate() { + let init = element .items .iter() .map(|item| { @@ -194,7 +194,7 @@ impl Store { }) .collect::>>()?; - let items = match elem.kind { + let items = match element.kind { // doesn't need to be initialized, can be initialized lazily using the `table.init` instruction ElementKind::Passive => Some(init), @@ -228,7 +228,7 @@ impl Store { } }; - self.data.elems.push(ElemInstance::new(elem.kind, idx, items)); + self.data.elements.push(ElementInstance::new(element.kind, idx, items)); elem_addrs.push((i + elem_count) as Addr); } @@ -262,7 +262,7 @@ impl Store { let offset = self.eval_i32_const(&offset)?; let mem = - self.data.mems.get_mut(mem_addr as usize).ok_or_else(|| { + self.data.memories.get_mut(mem_addr as usize).ok_or_else(|| { Error::Other(format!("memory {} not found for data segment {}", mem_addr, i)) })?; @@ -296,8 +296,8 @@ impl Store { if let MemoryArch::I64 = mem.arch { return Err(Error::UnsupportedFeature("64-bit memories".to_string())); } - self.data.mems.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); - Ok(self.data.mems.len() as MemAddr - 1) + self.data.memories.push(Rc::new(RefCell::new(MemoryInstance::new(mem, idx)))); + Ok(self.data.memories.len() as MemAddr - 1) } pub(crate) fn add_func(&mut self, func: Function, type_idx: TypeAddr, idx: ModuleInstanceAddr) -> Result { @@ -348,7 +348,7 @@ impl Store { /// Get the memory at the actual index in the store pub(crate) fn get_mem(&self, addr: usize) -> Result<&Rc>> { - self.data.mems.get(addr).ok_or_else(|| Error::Other(format!("memory {} not found", addr))) + self.data.memories.get(addr).ok_or_else(|| Error::Other(format!("memory {} not found", addr))) } /// Get the table at the actual index in the store @@ -357,8 +357,8 @@ impl Store { } /// Get the element at the actual index in the store - pub(crate) fn get_elem(&self, addr: usize) -> Result<&ElemInstance> { - self.data.elems.get(addr).ok_or_else(|| Error::Other(format!("element {} not found", addr))) + pub(crate) fn get_elem(&self, addr: usize) -> Result<&ElementInstance> { + self.data.elements.get(addr).ok_or_else(|| Error::Other(format!("element {} not found", addr))) } /// Get the global at the actual index in the store @@ -413,25 +413,29 @@ impl FunctionInstance { /// See #[derive(Debug)] pub(crate) struct TableInstance { - pub(crate) elements: Vec, + pub(crate) elements: Vec>, pub(crate) _kind: TableType, pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl TableInstance { pub(crate) fn new(kind: TableType, owner: ModuleInstanceAddr) -> Self { - Self { elements: vec![0; kind.size_initial as usize], _kind: kind, _owner: owner } + Self { elements: vec![None; kind.size_initial as usize], _kind: kind, _owner: owner } } pub(crate) fn get(&self, addr: usize) -> Result { - self.elements.get(addr).copied().ok_or_else(|| Trap::UndefinedElement { index: addr }.into()) + self.elements + .get(addr) + .copied() + .ok_or_else(|| Error::Trap(Trap::UndefinedElement { index: addr })) + .map(|elem| elem.ok_or_else(|| Trap::UninitializedElement { index: addr }.into()))? } pub(crate) fn set(&mut self, addr: usize, value: Addr) -> Result<()> { if addr >= self.elements.len() { return Err(Error::Other(format!("table element {} not found", addr))); } - self.elements[addr] = value; + self.elements[addr] = Some(value); Ok(()) } @@ -440,6 +444,8 @@ impl TableInstance { } pub(crate) fn init(&mut self, offset: i32, init: &[Addr]) -> Result<()> { + let init = init.iter().map(|item| Some(*item)).collect::>(); + let offset = offset as usize; let end = offset.checked_add(init.len()).ok_or_else(|| { Error::Trap(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() }) @@ -449,7 +455,7 @@ impl TableInstance { return Err(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() }.into()); } - self.elements[offset..end].copy_from_slice(init); + self.elements[offset..end].copy_from_slice(&init); Ok(()) } } @@ -573,13 +579,13 @@ impl GlobalInstance { /// /// See #[derive(Debug)] -pub(crate) struct ElemInstance { +pub(crate) struct ElementInstance { pub(crate) kind: ElementKind, pub(crate) items: Option>, // none is the element was dropped _owner: ModuleInstanceAddr, // index into store.module_instances } -impl ElemInstance { +impl ElementInstance { pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option>) -> Self { Self { kind, _owner: owner, items } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 3c3efcb..472bd35 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20100,128,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":169,"failed":1},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":86,"failed":13},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":108,"failed":75},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":93,"failed":39},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20113,115,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":85,"failed":14},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":102,"failed":30},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 86912c5..9b97cfd 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20087) +v0.3.0-alpha.0 (20113) + - - + diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs index c90f3df..d5de50a 100644 --- a/crates/types/src/instructions.rs +++ b/crates/types/src/instructions.rs @@ -11,7 +11,7 @@ pub enum BlockArgs { /// Represents a memory immediate in a WebAssembly memory instruction. #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct MemArg { +pub struct MemoryArg { pub mem_addr: MemAddr, pub align: u8, pub align_max: u8, @@ -82,29 +82,29 @@ pub enum Instruction { GlobalSet(GlobalAddr), // Memory Instructions - I32Load(MemArg), - I64Load(MemArg), - F32Load(MemArg), - F64Load(MemArg), - I32Load8S(MemArg), - I32Load8U(MemArg), - I32Load16S(MemArg), - I32Load16U(MemArg), - I64Load8S(MemArg), - I64Load8U(MemArg), - I64Load16S(MemArg), - I64Load16U(MemArg), - I64Load32S(MemArg), - I64Load32U(MemArg), - I32Store(MemArg), - I64Store(MemArg), - F32Store(MemArg), - F64Store(MemArg), - I32Store8(MemArg), - I32Store16(MemArg), - I64Store8(MemArg), - I64Store16(MemArg), - I64Store32(MemArg), + I32Load(MemoryArg), + I64Load(MemoryArg), + F32Load(MemoryArg), + F64Load(MemoryArg), + I32Load8S(MemoryArg), + I32Load8U(MemoryArg), + I32Load16S(MemoryArg), + I32Load16U(MemoryArg), + I64Load8S(MemoryArg), + I64Load8U(MemoryArg), + I64Load16S(MemoryArg), + I64Load16U(MemoryArg), + I64Load32S(MemoryArg), + I64Load32U(MemoryArg), + I32Store(MemoryArg), + I64Store(MemoryArg), + F32Store(MemoryArg), + F64Store(MemoryArg), + I32Store8(MemoryArg), + I32Store16(MemoryArg), + I64Store8(MemoryArg), + I64Store16(MemoryArg), + I64Store32(MemoryArg), MemorySize(MemAddr, u8), MemoryGrow(MemAddr, u8), From ec26f4bf4e0ab381b9a194659c1bf71a3b1b19f5 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 23 Jan 2024 19:02:29 +0100 Subject: [PATCH 34/52] feat: preserve null refs when returning Signed-off-by: Henry Gressmann --- crates/parser/src/conversion.rs | 4 +-- crates/tinywasm/src/runtime/executor/mod.rs | 10 ++++-- crates/tinywasm/src/runtime/value.rs | 27 ++++++++++------ crates/tinywasm/src/store.rs | 27 ++++++++++------ crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 8 ++--- crates/tinywasm/tests/testsuite/run.rs | 4 ++- crates/tinywasm/tests/testsuite/util.rs | 16 +++++----- crates/types/src/lib.rs | 32 +++++++++++-------- 9 files changed, 78 insertions(+), 52 deletions(-) diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index 1448d59..6045db1 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -202,8 +202,8 @@ pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> ValType { F32 => ValType::F32, F64 => ValType::F64, V128 => unimplemented!("128-bit values are not supported yet"), - FuncRef => ValType::FuncRef, - ExternRef => ValType::ExternRef, + FuncRef => ValType::RefFunc, + ExternRef => ValType::RefExtern, } } diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 3420dda..84051fc 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -171,7 +171,11 @@ fn exec_one( let call_ty = module.func_ty(*type_addr); let func_idx = stack.values.pop_t::()?; - let actual_func_addr = table.borrow().get(func_idx as usize)?; + let actual_func_addr = table + .borrow() + .get(func_idx as usize)? + .ok_or_else(|| Trap::UninitializedElement { index: func_idx as usize })?; + let resolved_func_addr = module.resolve_func_addr(actual_func_addr); // prepare the call frame @@ -565,12 +569,12 @@ fn exec_one( I64TruncF32U => checked_conv_float!(f32, u64, i64, stack), I64TruncF64U => checked_conv_float!(f64, u64, i64, stack), - // TODO: uninitialized element traps TableGet(table_index) => { let table_idx = module.resolve_table_addr(*table_index); let table = store.get_table(table_idx as usize)?; let idx = stack.values.pop_t::()? as usize; - stack.values.push(table.borrow().get(idx)?.into()); + let v = table.borrow().get_wasm_val(idx)?; + stack.values.push(v.into()); } TableSet(table_index) => { diff --git a/crates/tinywasm/src/runtime/value.rs b/crates/tinywasm/src/runtime/value.rs index c01617e..7230830 100644 --- a/crates/tinywasm/src/runtime/value.rs +++ b/crates/tinywasm/src/runtime/value.rs @@ -27,14 +27,20 @@ impl RawWasmValue { ValType::I64 => WasmValue::I64(self.0 as i64), ValType::F32 => WasmValue::F32(f32::from_bits(self.0 as u32)), ValType::F64 => WasmValue::F64(f64::from_bits(self.0)), - ValType::ExternRef => WasmValue::RefExtern(match self.0 { - 0 => None, - _ => Some(self.0 as u32), - }), - ValType::FuncRef => WasmValue::RefFunc(match self.0 { - 0 => None, - _ => Some(self.0 as u32), - }), + ValType::RefExtern => { + if self.0 == -1i64 as u64 { + WasmValue::RefNull(ValType::RefExtern) + } else { + WasmValue::RefExtern(self.0 as u32) + } + } + ValType::RefFunc => { + if self.0 == -1i64 as u64 { + WasmValue::RefNull(ValType::RefFunc) + } else { + WasmValue::RefFunc(self.0 as u32) + } + } } } } @@ -46,8 +52,9 @@ impl From for RawWasmValue { WasmValue::I64(i) => Self(i as u64), WasmValue::F32(i) => Self(i.to_bits() as u64), WasmValue::F64(i) => Self(i.to_bits()), - WasmValue::RefExtern(v) => Self(v.unwrap_or(0) as u64), - WasmValue::RefFunc(v) => Self(v.unwrap_or(0) as u64), + WasmValue::RefExtern(v) => Self(v as i64 as u64), + WasmValue::RefFunc(v) => Self(v as i64 as u64), + WasmValue::RefNull(_) => Self(-1i64 as u64), } } } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 730dbd7..9c4e7e6 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -335,7 +335,7 @@ impl Store { let val = global.borrow().value; val } - RefNull(v) => v.default_value().into(), + RefNull(_) => RawWasmValue::from(0), RefFunc(idx) => RawWasmValue::from(*idx as i64), }; Ok(val) @@ -414,27 +414,36 @@ impl FunctionInstance { #[derive(Debug)] pub(crate) struct TableInstance { pub(crate) elements: Vec>, - pub(crate) _kind: TableType, + pub(crate) kind: TableType, pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl TableInstance { pub(crate) fn new(kind: TableType, owner: ModuleInstanceAddr) -> Self { - Self { elements: vec![None; kind.size_initial as usize], _kind: kind, _owner: owner } + Self { elements: vec![None; kind.size_initial as usize], kind, _owner: owner } } - pub(crate) fn get(&self, addr: usize) -> Result { - self.elements - .get(addr) - .copied() - .ok_or_else(|| Error::Trap(Trap::UndefinedElement { index: addr })) - .map(|elem| elem.ok_or_else(|| Trap::UninitializedElement { index: addr }.into()))? + pub(crate) fn get_wasm_val(&self, addr: usize) -> Result { + Ok(match self.kind.element_type { + ValType::RefFunc => { + self.get(addr)?.map(|v| WasmValue::RefFunc(v)).unwrap_or(WasmValue::RefNull(ValType::RefFunc)) + } + ValType::RefExtern => { + self.get(addr)?.map(|v| WasmValue::RefExtern(v)).unwrap_or(WasmValue::RefNull(ValType::RefExtern)) + } + _ => unimplemented!("unsupported table type: {:?}", self.kind.element_type), + }) + } + + pub(crate) fn get(&self, addr: usize) -> Result> { + self.elements.get(addr).copied().ok_or_else(|| Error::Trap(Trap::UndefinedElement { index: addr })) } pub(crate) fn set(&mut self, addr: usize, value: Addr) -> Result<()> { if addr >= self.elements.len() { return Err(Error::Other(format!("table element {} not found", addr))); } + self.elements[addr] = Some(value); Ok(()) } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 472bd35..eee0b45 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20113,115,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":85,"failed":14},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":102,"failed":30},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20112,116,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":86,"failed":13},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":108,"failed":2},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":102,"failed":30},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 9b97cfd..8a0128f 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20113) +v0.3.0-alpha.0 (20112) - - - + + + diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 6f719f9..44c349c 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -83,7 +83,7 @@ impl TestSuite { let mut imports = Imports::new(); let table = - Extern::table(TableType::new(ValType::FuncRef, 10, Some(20)), WasmValue::default_for(ValType::FuncRef)); + Extern::table(TableType::new(ValType::RefFunc, 10, Some(20)), WasmValue::default_for(ValType::RefFunc)); let print = Extern::typed_func(|_ctx: tinywasm::FuncContext, _: ()| { log::debug!("print"); @@ -464,6 +464,8 @@ impl TestSuite { )); } + log::debug!("outcomes: {:?}", outcomes); + outcomes.iter().zip(expected).enumerate().try_for_each(|(i, (outcome, exp))| { (outcome.eq_loose(&exp)) .then_some(()) diff --git a/crates/tinywasm/tests/testsuite/util.rs b/crates/tinywasm/tests/testsuite/util.rs index a3bb1a1..b74eec5 100644 --- a/crates/tinywasm/tests/testsuite/util.rs +++ b/crates/tinywasm/tests/testsuite/util.rs @@ -1,7 +1,7 @@ use std::panic::{self, AssertUnwindSafe}; use eyre::{eyre, Result}; -use tinywasm_types::{ModuleInstanceAddr, TinyWasmModule, WasmValue}; +use tinywasm_types::{ModuleInstanceAddr, TinyWasmModule, ValType, WasmValue}; pub fn try_downcast_panic(panic: Box) -> String { let info = panic.downcast_ref::().or(None).map(|p| p.to_string()).clone(); @@ -77,10 +77,10 @@ fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result WasmValue::F64(f64::from_bits(f.bits)), I32(i) => WasmValue::I32(i), I64(i) => WasmValue::I64(i), - RefExtern(v) => WasmValue::RefExtern(Some(v)), + RefExtern(v) => WasmValue::RefExtern(v), RefNull(t) => match t { - wast::core::HeapType::Func => WasmValue::RefFunc(None), - wast::core::HeapType::Extern => WasmValue::RefExtern(None), + wast::core::HeapType::Func => WasmValue::RefNull(ValType::RefFunc), + wast::core::HeapType::Extern => WasmValue::RefNull(ValType::RefExtern), _ => return Err(eyre!("unsupported arg type: refnull: {:?}", t)), }, v => return Err(eyre!("unsupported arg type: {:?}", v)), @@ -99,16 +99,16 @@ fn wastret2tinywasmvalue(arg: wast::WastRet) -> Result WasmValue::I32(i), I64(i) => WasmValue::I64(i), RefNull(t) => match t { - Some(wast::core::HeapType::Func) => WasmValue::RefFunc(None), - Some(wast::core::HeapType::Extern) => WasmValue::RefExtern(None), + Some(wast::core::HeapType::Func) => WasmValue::RefNull(ValType::RefFunc), + Some(wast::core::HeapType::Extern) => WasmValue::RefNull(ValType::RefExtern), _ => return Err(eyre!("unsupported arg type: refnull: {:?}", t)), }, RefExtern(v) => match v { - Some(v) => WasmValue::RefExtern(Some(v)), + Some(v) => WasmValue::RefExtern(v), _ => return Err(eyre!("unsupported arg type: refextern: {:?}", v)), }, RefFunc(v) => match v { - Some(wast::token::Index::Num(n, _)) => WasmValue::RefFunc(Some(n)), + Some(wast::token::Index::Num(n, _)) => WasmValue::RefFunc(n), _ => return Err(eyre!("unsupported arg type: reffunc: {:?}", v)), }, a => return Err(eyre!("unsupported arg type {:?}", a)), diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 87581e1..8872479 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -83,11 +83,10 @@ pub enum WasmValue { F32(f32), /// A 64-bit float. F64(f64), - // Vec types - // V128(i128), - // RefHost(FuncAddr), - RefExtern(Option), - RefFunc(Option), + + RefExtern(ExternAddr), + RefFunc(FuncAddr), + RefNull(ValType), } impl WasmValue { @@ -97,8 +96,10 @@ impl WasmValue { Self::I64(i) => ConstInstruction::I64Const(*i), Self::F32(i) => ConstInstruction::F32Const(*i), Self::F64(i) => ConstInstruction::F64Const(*i), - Self::RefExtern(None) => ConstInstruction::RefNull(ValType::ExternRef), - Self::RefFunc(None) => ConstInstruction::RefNull(ValType::FuncRef), + + Self::RefFunc(i) => ConstInstruction::RefFunc(*i), + Self::RefNull(ty) => ConstInstruction::RefNull(*ty), + // Self::RefExtern(addr) => ConstInstruction::RefExtern(*addr), _ => unimplemented!("no const_instr for {:?}", self), } @@ -111,8 +112,8 @@ impl WasmValue { ValType::I64 => Self::I64(0), ValType::F32 => Self::F32(0.0), ValType::F64 => Self::F64(0.0), - ValType::FuncRef => Self::RefFunc(None), - ValType::ExternRef => Self::RefExtern(None), + ValType::RefFunc => Self::RefNull(ValType::RefFunc), + ValType::RefExtern => Self::RefNull(ValType::RefExtern), } } @@ -120,6 +121,7 @@ impl WasmValue { match (self, other) { (Self::I32(a), Self::I32(b)) => a == b, (Self::I64(a), Self::I64(b)) => a == b, + (Self::RefNull(v), Self::RefNull(v2)) => v == v2, (Self::RefExtern(addr), Self::RefExtern(addr2)) => addr == addr2, (Self::RefFunc(addr), Self::RefFunc(addr2)) => addr == addr2, (Self::F32(a), Self::F32(b)) => { @@ -230,6 +232,7 @@ impl Debug for WasmValue { WasmValue::F64(i) => write!(f, "f64({})", i), WasmValue::RefExtern(addr) => write!(f, "ref.extern({:?})", addr), WasmValue::RefFunc(addr) => write!(f, "ref.func({:?})", addr), + WasmValue::RefNull(ty) => write!(f, "ref.null({:?})", ty), // WasmValue::V128(i) => write!(f, "v128({})", i), } } @@ -243,8 +246,9 @@ impl WasmValue { Self::I64(_) => ValType::I64, Self::F32(_) => ValType::F32, Self::F64(_) => ValType::F64, - Self::RefExtern(_) => ValType::ExternRef, - Self::RefFunc(_) => ValType::FuncRef, + Self::RefExtern(_) => ValType::RefExtern, + Self::RefFunc(_) => ValType::RefFunc, + Self::RefNull(ty) => *ty, } } } @@ -261,9 +265,9 @@ pub enum ValType { /// A 64-bit float. F64, /// A reference to a function. - FuncRef, + RefFunc, /// A reference to an external value. - ExternRef, + RefExtern, } impl ValType { @@ -392,7 +396,7 @@ pub struct TableType { impl TableType { pub fn empty() -> Self { - Self { element_type: ValType::FuncRef, size_initial: 0, size_max: None } + Self { element_type: ValType::RefFunc, size_initial: 0, size_max: None } } pub fn new(element_type: ValType, size_initial: u32, size_max: Option) -> Self { From baf9942e9ed8fa9a13c85ec8b51cc0a3de03b562 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 23 Jan 2024 19:15:51 +0100 Subject: [PATCH 35/52] fix: global refnull conversion Signed-off-by: Henry Gressmann --- crates/parser/src/conversion.rs | 1 - crates/tinywasm/src/store.rs | 2 +- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/generated/progress-mvp.svg | 14 +++++++------- crates/wasm-testsuite/lib.rs | 7 ++----- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index 6045db1..be6a4e5 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -226,7 +226,6 @@ pub fn process_const_operator(op: wasmparser::Operator) -> Result Ok(ConstInstruction::RefNull(convert_valtype(&ty))), wasmparser::Operator::RefFunc { function_index } => Ok(ConstInstruction::RefFunc(function_index)), - wasmparser::Operator::I32Const { value } => Ok(ConstInstruction::I32Const(value)), wasmparser::Operator::I64Const { value } => Ok(ConstInstruction::I64Const(value)), wasmparser::Operator::F32Const { value } => Ok(ConstInstruction::F32Const(f32::from_bits(value.bits()))), // TODO: check if this is correct diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 9c4e7e6..b4ba086 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -335,7 +335,7 @@ impl Store { let val = global.borrow().value; val } - RefNull(_) => RawWasmValue::from(0), + RefNull(t) => RawWasmValue::from(t.default_value()), RefFunc(idx) => RawWasmValue::from(*idx as i64), }; Ok(val) diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index eee0b45..85fdd92 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20112,116,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":86,"failed":13},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":108,"failed":2},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":102,"failed":30},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20140,114,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":86,"failed":13},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":102,"failed":30},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 8a0128f..a7c27e4 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -12,7 +12,7 @@ TinyWasm Version - + @@ -27,10 +27,10 @@ TinyWasm Version 10000 - + 15000 - + 20000 @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20112) +v0.3.0-alpha.0 (20140) - - - + + + diff --git a/crates/wasm-testsuite/lib.rs b/crates/wasm-testsuite/lib.rs index 9e38bfc..e3352fb 100644 --- a/crates/wasm-testsuite/lib.rs +++ b/crates/wasm-testsuite/lib.rs @@ -2,10 +2,7 @@ #![forbid(unsafe_code)] #![doc(test( no_crate_inject, - attr( - deny(warnings, rust_2018_idioms), - allow(dead_code, unused_assignments, unused_variables) - ) + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_assignments, unused_variables)) ))] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] @@ -26,7 +23,7 @@ pub const PROPOSALS: &[&str] = &["annotations", "exception-handling", "memory64" /// List of all tests that apply to the MVP (V1) spec. /// Note that the tests are still for the latest spec, so the latest version of Wast is used. #[rustfmt::skip] // removed: "break-drop.wast", -pub const MVP_TESTS: &[&str] = &["address.wast","align.wast","binary-leb128.wast","binary.wast","block.wast","br.wast","br_if.wast","br_table.wast","call.wast","call_indirect.wast","comments.wast","const.wast","conversions.wast","custom.wast","data.wast","elem.wast","endianness.wast","exports.wast","f32.wast","f32_bitwise.wast","f32_cmp.wast","f64.wast","f64_bitwise.wast","f64_cmp.wast","fac.wast","float_exprs.wast","float_literals.wast","float_memory.wast","float_misc.wast","forward.wast","func.wast","func_ptrs.wast","global.wast","i32.wast","i64.wast","if.wast","imports.wast","inline-module.wast","int_exprs.wast","int_literals.wast","labels.wast","left-to-right.wast","linking.wast","load.wast","local_get.wast","local_set.wast","local_tee.wast","loop.wast","memory.wast","memory_grow.wast","memory_redundancy.wast","memory_size.wast","memory_trap.wast","names.wast","nop.wast","return.wast","select.wast","skip-stack-guard-page.wast","stack.wast","start.wast","store.wast","switch.wast","token.wast","traps.wast","type.wast","unreachable.wast","unreached-invalid.wast","unwind.wast","utf8-custom-section-id.wast","utf8-import-field.wast","utf8-import-module.wast","utf8-invalid-encoding.wast"]; +pub const MVP_TESTS: &[&str] = &["address.wast","align.wast","binary-leb128.wast","binary.wast","block.wast","br.wast","br_if.wast","br_table.wast","call.wast","call_indirect.wast","comments.wast","const.wast","conversions.wast","custom.wast","data.wast","elem.wast","endianness.wast","exports.wast","f32.wast","f32_bitwise.wast","f32_cmp.wast","f64.wast","f64_bitwise.wast","f64_cmp.wast","fac.wast","float_exprs.wast","float_literals.wast","float_memory.wast","float_misc.wast","forward.wast","func.wast","func_ptrs.wast","global.wast","i32.wast","i64.wast","if.wast","imports.wast","inline-module.wast","int_exprs.wast","int_literals.wast","labels.wast","left-to-right.wast","linking.wast","load.wast","local_get.wast","local_set.wast","local_tee.wast","loop.wast","memory.wast","memory_grow.wast","memory_redundancy.wast","memory_size.wast","memory_trap.wast","names.wast","nop.wast","return.wast","select.wast","skip-stack-guard-page.wast","stack.wast","start.wast","store.wast","switch.wast","table.wast","token.wast","traps.wast","type.wast","unreachable.wast","unreached-valid.wast","unreached-invalid.wast","unwind.wast","utf8-custom-section-id.wast","utf8-import-field.wast","utf8-import-module.wast","utf8-invalid-encoding.wast"]; /// List of all tests that apply to the V2 draft 1 spec. #[rustfmt::skip] From 2da20207b7c398b5e479d8a9fae68f06d1ef7924 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 23 Jan 2024 21:14:15 +0100 Subject: [PATCH 36/52] feat: shared tables across modules Signed-off-by: Henry Gressmann --- ARCHITECTURE.md | 1 + Cargo.lock | 6 +- crates/parser/src/conversion.rs | 9 +-- crates/tinywasm/src/instance.rs | 4 +- crates/tinywasm/src/runtime/executor/mod.rs | 19 +++--- crates/tinywasm/src/store.rs | 66 ++++++++++++++------- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/testsuite/run.rs | 2 - 8 files changed, 65 insertions(+), 44 deletions(-) create mode 100644 ARCHITECTURE.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..8705e5a --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1 @@ +# TinyWasm's Architecture diff --git a/Cargo.lock b/Cargo.lock index ec25d02..e13a9f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,16 +210,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.0", ] [[package]] diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index be6a4e5..1808447 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -184,11 +184,6 @@ pub(crate) fn convert_blocktype(blocktype: wasmparser::BlockType) -> BlockArgs { use wasmparser::BlockType::*; match blocktype { Empty => BlockArgs::Empty, - - // We should maybe have all this in a single variant for our custom bytecode - - // TODO: maybe solve this differently so we can support 128-bit values - // without having to increase the size of the WasmValue enum Type(ty) => BlockArgs::Type(convert_valtype(&ty)), FuncType(ty) => BlockArgs::FuncType(ty), } @@ -228,8 +223,8 @@ pub fn process_const_operator(op: wasmparser::Operator) -> Result Ok(ConstInstruction::RefFunc(function_index)), wasmparser::Operator::I32Const { value } => Ok(ConstInstruction::I32Const(value)), wasmparser::Operator::I64Const { value } => Ok(ConstInstruction::I64Const(value)), - wasmparser::Operator::F32Const { value } => Ok(ConstInstruction::F32Const(f32::from_bits(value.bits()))), // TODO: check if this is correct - wasmparser::Operator::F64Const { value } => Ok(ConstInstruction::F64Const(f64::from_bits(value.bits()))), // TODO: check if this is correct + wasmparser::Operator::F32Const { value } => Ok(ConstInstruction::F32Const(f32::from_bits(value.bits()))), + wasmparser::Operator::F64Const { value } => Ok(ConstInstruction::F64Const(f64::from_bits(value.bits()))), wasmparser::Operator::GlobalGet { global_index } => Ok(ConstInstruction::GlobalGet(global_index)), op => Err(crate::ParseError::UnsupportedOperator(format!("Unsupported const instruction: {:?}", op))), } diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 11deedc..aa94efa 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -57,6 +57,7 @@ impl ModuleInstance { // don't need to create a auxiliary frame etc. let idx = store.next_module_instance_idx(); + log::error!("Instantiating module at index {}", idx); let imports = imports.unwrap_or_default(); let mut addrs = imports.link(store, &module, idx)?; @@ -68,13 +69,12 @@ impl ModuleInstance { addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?); addrs.memories.extend(store.init_memories(data.memory_types.into(), idx)?); - let elem_addrs = store.init_elements(&addrs.tables, data.elements.into(), idx)?; + let elem_addrs = store.init_elements(&addrs.tables, &addrs.funcs, data.elements.into(), idx)?; let data_addrs = store.init_datas(&addrs.memories, data.data.into(), idx)?; let instance = ModuleInstanceInner { store_id: store.id(), idx, - types: data.func_types, func_addrs: addrs.funcs.into_boxed_slice(), table_addrs: addrs.tables.into_boxed_slice(), diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 84051fc..42a2dc0 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -7,7 +7,7 @@ use crate::{ CallFrame, Error, FuncContext, LabelArgs, ModuleInstance, Result, Store, Trap, }; use alloc::{string::ToString, vec::Vec}; -use tinywasm_types::{ElementKind, Instruction}; +use tinywasm_types::{ElementKind, Instruction, ValType}; mod macros; mod traits; @@ -171,15 +171,17 @@ fn exec_one( let call_ty = module.func_ty(*type_addr); let func_idx = stack.values.pop_t::()?; - let actual_func_addr = table + + // verify that the table is of the right type, this should be validated by the parser already + assert!(table.borrow().kind.element_type == ValType::RefFunc, "table is not of type funcref"); + + let func_ref = table .borrow() .get(func_idx as usize)? + .addr() .ok_or_else(|| Trap::UninitializedElement { index: func_idx as usize })?; - let resolved_func_addr = module.resolve_func_addr(actual_func_addr); - - // prepare the call frame - let func_inst = store.get_func(resolved_func_addr as usize)?; + let func_inst = store.get_func(func_ref as usize)?; let func_ty = func_inst.func.ty(); let func = match &func_inst.func { @@ -200,8 +202,7 @@ fn exec_one( } let params = stack.values.pop_n_rev(func_ty.params.len())?; - let call_frame = - CallFrame::new_raw(resolved_func_addr as usize, ¶ms, func.locals.to_vec(), func_inst._owner); + let call_frame = CallFrame::new_raw(func_ref as usize, ¶ms, func.locals.to_vec(), func_inst._owner); // push the call frame cf.instr_ptr += 1; // skip the call instruction @@ -606,7 +607,7 @@ fn exec_one( return Err(Trap::TableOutOfBounds { offset: 0, len: 0, max: 0 }.into()); }; - table.borrow_mut().init(0, items)?; + table.borrow_mut().init(module.func_addrs(), 0, items)?; } I32TruncSatF32S => arithmetic_single!(trunc, f32, i32, stack), diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index b4ba086..4d33476 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -82,7 +82,6 @@ impl Default for Store { /// /// Data should only be addressable by the module that owns it /// See -// TODO: Arena allocate these? pub(crate) struct StoreData { pub(crate) funcs: Vec>, pub(crate) tables: Vec>>, @@ -178,6 +177,7 @@ impl Store { pub(crate) fn init_elements( &mut self, table_addrs: &[TableAddr], + func_addrs: &[FuncAddr], elements: Vec, idx: ModuleInstanceAddr, ) -> Result> { @@ -194,6 +194,8 @@ impl Store { }) .collect::>>()?; + log::error!("element kind: {:?}", element.kind); + let items = match element.kind { // doesn't need to be initialized, can be initialized lazily using the `table.init` instruction ElementKind::Passive => Some(init), @@ -218,7 +220,7 @@ impl Store { // d. Execute the instruction i32.const n // e. Execute the instruction table.init tableidx i if let Some(table) = self.data.tables.get_mut(table_addr as usize) { - table.borrow_mut().init(offset, &init)?; + table.borrow_mut().init(func_addrs, offset, &init)?; } else { log::error!("table {} not found", table); } @@ -385,8 +387,6 @@ impl Store { /// See pub struct FunctionInstance { pub(crate) func: Function, - - // TODO: this is important for call_indirect pub(crate) _type_idx: TypeAddr, pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions } @@ -408,43 +408,58 @@ impl FunctionInstance { } } +#[derive(Debug, Clone, Copy)] +pub(crate) enum TableElement { + Uninitialized, + Initialized(Addr), +} + +impl TableElement { + pub(crate) fn addr(&self) -> Option { + match self { + TableElement::Uninitialized => None, + TableElement::Initialized(addr) => Some(*addr), + } + } +} + /// A WebAssembly Table Instance /// /// See #[derive(Debug)] pub(crate) struct TableInstance { - pub(crate) elements: Vec>, + pub(crate) elements: Vec, pub(crate) kind: TableType, pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl TableInstance { pub(crate) fn new(kind: TableType, owner: ModuleInstanceAddr) -> Self { - Self { elements: vec![None; kind.size_initial as usize], kind, _owner: owner } + Self { elements: vec![TableElement::Uninitialized; kind.size_initial as usize], kind, _owner: owner } } pub(crate) fn get_wasm_val(&self, addr: usize) -> Result { + let val = self.get(addr)?.addr(); + Ok(match self.kind.element_type { - ValType::RefFunc => { - self.get(addr)?.map(|v| WasmValue::RefFunc(v)).unwrap_or(WasmValue::RefNull(ValType::RefFunc)) - } + ValType::RefFunc => val.map(|v| WasmValue::RefFunc(v)).unwrap_or(WasmValue::RefNull(ValType::RefFunc)), ValType::RefExtern => { - self.get(addr)?.map(|v| WasmValue::RefExtern(v)).unwrap_or(WasmValue::RefNull(ValType::RefExtern)) + val.map(|v| WasmValue::RefExtern(v)).unwrap_or(WasmValue::RefNull(ValType::RefExtern)) } _ => unimplemented!("unsupported table type: {:?}", self.kind.element_type), }) } - pub(crate) fn get(&self, addr: usize) -> Result> { - self.elements.get(addr).copied().ok_or_else(|| Error::Trap(Trap::UndefinedElement { index: addr })) + pub(crate) fn get(&self, addr: usize) -> Result<&TableElement> { + self.elements.get(addr).ok_or_else(|| Error::Trap(Trap::UndefinedElement { index: addr })) } - pub(crate) fn set(&mut self, addr: usize, value: Addr) -> Result<()> { - if addr >= self.elements.len() { - return Err(Error::Other(format!("table element {} not found", addr))); - } - - self.elements[addr] = Some(value); + pub(crate) fn set(&mut self, table_idx: usize, value: Addr) -> Result<()> { + let el = self + .elements + .get_mut(table_idx) + .ok_or_else(|| Error::Other(format!("table element {} not found", table_idx)))?; + *el = TableElement::Initialized(value); Ok(()) } @@ -452,8 +467,18 @@ impl TableInstance { self.elements.len() as i32 } - pub(crate) fn init(&mut self, offset: i32, init: &[Addr]) -> Result<()> { - let init = init.iter().map(|item| Some(*item)).collect::>(); + pub(crate) fn init(&mut self, func_addrs: &[u32], offset: i32, init: &[Addr]) -> Result<()> { + let init = init + .iter() + .map(|item| { + TableElement::Initialized(match self.kind.element_type == ValType::RefFunc { + true => *func_addrs.get(*item as usize).expect( + "error initializing table: function not found. This should have been caught by the validator", + ), + false => *item, + }) + }) + .collect::>(); let offset = offset as usize; let end = offset.checked_add(init.len()).ok_or_else(|| { @@ -465,6 +490,7 @@ impl TableInstance { } self.elements[offset..end].copy_from_slice(&init); + log::debug!("table: {:?}", self.elements); Ok(()) } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 85fdd92..a8dd2b5 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20140,114,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":86,"failed":13},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":102,"failed":30},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20151,103,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":91,"failed":8},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":108,"failed":24},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index 44c349c..fc8977a 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -193,8 +193,6 @@ impl TestSuite { } Wat(module) => { - // TODO: modules are not properly isolated from each other - tests fail because of this otherwise - // store = tinywasm::Store::default(); debug!("got wat module"); let result = catch_unwind_silent(|| { let (name, bytes) = match module { From 31df65ad9b92eb886da2a44afc06925c1be6d568 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 23 Jan 2024 22:08:49 +0100 Subject: [PATCH 37/52] chore: refactor executer, change the module when executing imported functions Signed-off-by: Henry Gressmann --- crates/tinywasm/src/func.rs | 12 +-- crates/tinywasm/src/instance.rs | 8 +- crates/tinywasm/src/runtime/executor/mod.rs | 87 ++++++++++--------- .../tinywasm/src/runtime/stack/call_stack.rs | 22 ++--- crates/tinywasm/src/store.rs | 12 ++- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 4 +- 7 files changed, 72 insertions(+), 75 deletions(-) diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 9f9d95a..8518af0 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -27,7 +27,7 @@ impl FuncHandle { // 1. Assert: funcs[func_addr] exists // 2. let func_inst be the functiuon instance funcs[func_addr] - let func_inst = store.get_func(self.addr as usize)?; + let func_inst = store.get_func(self.addr as usize)?.clone(); // 3. Let func_ty be the function type let func_ty = &self.ty; @@ -52,18 +52,18 @@ impl FuncHandle { } } - let wasm_func = match &func_inst.func { + let locals = match &func_inst.func { crate::Function::Host(h) => { let func = h.func.clone(); let ctx = FuncContext { store, module: &self.module }; return (func)(ctx, params); } - crate::Function::Wasm(ref f) => f, + crate::Function::Wasm(ref f) => f.locals.to_vec(), }; // 6. Let f be the dummy frame - debug!("locals: {:?}", wasm_func.locals); - let call_frame = CallFrame::new(self.addr as usize, params, wasm_func.locals.to_vec(), self.module.id()); + debug!("locals: {:?}", locals); + let call_frame = CallFrame::new(func_inst, params, locals); // 7. Push the frame f to the call stack // & 8. Push the values to the stack (Not needed since the call frame owns the values) @@ -71,7 +71,7 @@ impl FuncHandle { // 9. Invoke the function instance let runtime = store.runtime(); - runtime.exec(store, &mut stack, self.module.clone())?; + runtime.exec(store, &mut stack)?; // Once the function returns: let result_m = func_ty.results.len(); diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index aa94efa..d7298af 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -81,7 +81,7 @@ impl ModuleInstance { mem_addrs: addrs.memories.into_boxed_slice(), global_addrs: addrs.globals.into_boxed_slice(), elem_addrs, - data_addrs: data_addrs, + data_addrs, func_start: data.start_func, imports: data.imports, exports: data.exports, @@ -111,11 +111,7 @@ impl ModuleInstance { &self.0.func_addrs } - pub(crate) fn _global_addrs(&self) -> &[GlobalAddr] { - &self.0.global_addrs - } - - pub(crate) fn func_ty_addrs(&self) -> &[FuncType] { + pub(crate) fn func_tys(&self) -> &[FuncType] { &self.0.types } diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 42a2dc0..38d59d5 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -15,32 +15,32 @@ use macros::*; use traits::*; impl DefaultRuntime { - pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack, module: ModuleInstance) -> Result<()> { - log::debug!("func_addrs: {:?}", module.func_addrs()); - log::debug!("func_ty_addrs: {:?}", module.func_ty_addrs().len()); - log::debug!("store funcs: {:?}", store.data.funcs.len()); - + pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack) -> Result<()> { // The current call frame, gets updated inside of exec_one let mut cf = stack.call_stack.pop()?; - // The function to execute, gets updated from ExecResult::Call - let mut func_inst = store.get_func(cf.func_ptr)?.clone(); + let mut func_inst = cf.func_instance.clone(); let mut wasm_func = func_inst.assert_wasm().expect("exec expected wasm function"); + + // The function to execute, gets updated from ExecResult::Call let mut instrs = &wasm_func.instructions; - let mut current_module = module; + let mut current_module = store + .get_module_instance(func_inst.owner) + .expect("exec expected module instance to exist for function") + .clone(); while let Some(instr) = instrs.get(cf.instr_ptr) { match exec_one(&mut cf, instr, instrs, stack, store, ¤t_module)? { // Continue execution at the new top of the call stack ExecResult::Call => { cf = stack.call_stack.pop()?; - func_inst = store.get_func(cf.func_ptr)?.clone(); - wasm_func = func_inst.assert_wasm().expect("call expected wasm function"); + func_inst = cf.func_instance.clone(); + wasm_func = func_inst.assert_wasm().expect("exec expected wasm function"); instrs = &wasm_func.instructions; - if cf.module != current_module.id() { - current_module.swap(store.get_module_instance(cf.module).unwrap().clone()); + if cf.func_instance.owner != current_module.id() { + current_module.swap(store.get_module_instance(cf.func_instance.owner).unwrap().clone()); } continue; @@ -135,10 +135,10 @@ fn exec_one( log::info!("start call"); // prepare the call frame let func_idx = module.resolve_func_addr(*v); - let func_inst = store.get_func(func_idx as usize)?; + let func_inst = store.get_func(func_idx as usize)?.clone(); - let func = match &func_inst.func { - crate::Function::Wasm(ref f) => f, + let (locals, ty) = match &func_inst.func { + crate::Function::Wasm(ref f) => (f.locals.to_vec(), f.ty.clone()), crate::Function::Host(host_func) => { let func = host_func.func.clone(); log::info!("Getting params: {:?}", host_func.ty.params); @@ -150,8 +150,11 @@ fn exec_one( } }; - let params = stack.values.pop_n_rev(func.ty.params.len())?; - let call_frame = CallFrame::new_raw(func_idx as usize, ¶ms, func.locals.to_vec(), func_inst._owner); + let params = stack.values.pop_n_rev(ty.params.len())?; + log::info!("call: current fn owner: {:?}", module.id()); + log::info!("call: func owner: {:?}", func_inst.owner); + + let call_frame = CallFrame::new_raw(func_inst, ¶ms, locals); // push the call frame cf.instr_ptr += 1; // skip the call instruction @@ -163,29 +166,39 @@ fn exec_one( } CallIndirect(type_addr, table_addr) => { - let table_idx = module.resolve_table_addr(*table_addr); - let table = store.get_table(table_idx as usize)?; - - // TODO: currently, the type resolution is subtlely broken for imported functions - - let call_ty = module.func_ty(*type_addr); - - let func_idx = stack.values.pop_t::()?; + let table = store.get_table(module.resolve_table_addr(*table_addr) as usize)?; + let table_idx = stack.values.pop_t::()?; // verify that the table is of the right type, this should be validated by the parser already assert!(table.borrow().kind.element_type == ValType::RefFunc, "table is not of type funcref"); - let func_ref = table - .borrow() - .get(func_idx as usize)? - .addr() - .ok_or_else(|| Trap::UninitializedElement { index: func_idx as usize })?; + let func_ref = { + table + .borrow() + .get(table_idx as usize)? + .addr() + .ok_or(Trap::UninitializedElement { index: table_idx as usize })? + }; - let func_inst = store.get_func(func_ref as usize)?; + let func_inst = store.get_func(func_ref as usize)?.clone(); let func_ty = func_inst.func.ty(); - let func = match &func_inst.func { - crate::Function::Wasm(ref f) => f, + log::info!("type_addr: {}", type_addr); + log::info!("types: {:?}", module.func_tys()); + let call_ty = module.func_ty(*type_addr); + + log::info!("call_indirect: current fn owner: {:?}", module.id()); + log::info!("call_indirect: func owner: {:?}", func_inst.owner); + + if func_ty != call_ty { + log::error!("indirect call type mismatch: {:?} != {:?}", func_ty, call_ty); + return Err( + Trap::IndirectCallTypeMismatch { actual: func_ty.clone(), expected: call_ty.clone() }.into() + ); + } + + let locals = match &func_inst.func { + crate::Function::Wasm(ref f) => f.locals.to_vec(), crate::Function::Host(host_func) => { let func = host_func.func.clone(); let params = stack.values.pop_params(&func_ty.params)?; @@ -195,14 +208,8 @@ fn exec_one( } }; - if func_ty != call_ty { - return Err( - Trap::IndirectCallTypeMismatch { actual: func_ty.clone(), expected: call_ty.clone() }.into() - ); - } - let params = stack.values.pop_n_rev(func_ty.params.len())?; - let call_frame = CallFrame::new_raw(func_ref as usize, ¶ms, func.locals.to_vec(), func_inst._owner); + let call_frame = CallFrame::new_raw(func_inst, ¶ms, locals); // push the call frame cf.instr_ptr += 1; // skip the call instruction diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index b1c4f67..1bcd474 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -1,6 +1,6 @@ -use crate::{runtime::RawWasmValue, BlockType, Error, LabelFrame, Result, Trap}; -use alloc::{boxed::Box, vec::Vec}; -use tinywasm_types::{ModuleInstanceAddr, ValType, WasmValue}; +use crate::{runtime::RawWasmValue, BlockType, Error, FunctionInstance, LabelFrame, Result, Trap}; +use alloc::{boxed::Box, rc::Rc, vec::Vec}; +use tinywasm_types::{ValType, WasmValue}; use super::blocks::Labels; @@ -52,9 +52,9 @@ impl CallStack { #[derive(Debug, Clone)] pub(crate) struct CallFrame { - pub(crate) module: ModuleInstanceAddr, pub(crate) instr_ptr: usize, - pub(crate) func_ptr: usize, + // pub(crate) module: ModuleInstanceAddr, + pub(crate) func_instance: Rc, pub(crate) labels: Labels, pub(crate) locals: Box<[RawWasmValue]>, @@ -109,10 +109,9 @@ impl CallFrame { } pub(crate) fn new_raw( - func_ptr: usize, + func_instance_ptr: Rc, params: &[RawWasmValue], local_types: Vec, - module: ModuleInstanceAddr, ) -> Self { let mut locals = Vec::with_capacity(local_types.len() + params.len()); locals.extend(params.iter().cloned()); @@ -120,25 +119,22 @@ impl CallFrame { Self { instr_ptr: 0, - func_ptr, + func_instance: func_instance_ptr, local_count: locals.len(), locals: locals.into_boxed_slice(), labels: Labels::default(), - module, } } pub(crate) fn new( - func_ptr: usize, + func_instance_ptr: Rc, params: &[WasmValue], local_types: Vec, - module: ModuleInstanceAddr, ) -> Self { CallFrame::new_raw( - func_ptr, + func_instance_ptr, ¶ms.iter().map(|v| RawWasmValue::from(*v)).collect::>(), local_types, - module, ) } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 4d33476..9bbb125 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -121,7 +121,7 @@ impl Store { self.data.funcs.push(Rc::new(FunctionInstance { func: Function::Wasm(func), _type_idx: type_idx, - _owner: idx, + owner: idx, })); func_addrs.push((i + func_count) as FuncAddr); } @@ -303,7 +303,7 @@ impl Store { } pub(crate) fn add_func(&mut self, func: Function, type_idx: TypeAddr, idx: ModuleInstanceAddr) -> Result { - self.data.funcs.push(Rc::new(FunctionInstance { func, _type_idx: type_idx, _owner: idx })); + self.data.funcs.push(Rc::new(FunctionInstance { func, _type_idx: type_idx, owner: idx })); Ok(self.data.funcs.len() as FuncAddr - 1) } @@ -388,7 +388,7 @@ impl Store { pub struct FunctionInstance { pub(crate) func: Function, pub(crate) _type_idx: TypeAddr, - pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions + pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions } // TODO: check if this actually helps @@ -442,10 +442,8 @@ impl TableInstance { let val = self.get(addr)?.addr(); Ok(match self.kind.element_type { - ValType::RefFunc => val.map(|v| WasmValue::RefFunc(v)).unwrap_or(WasmValue::RefNull(ValType::RefFunc)), - ValType::RefExtern => { - val.map(|v| WasmValue::RefExtern(v)).unwrap_or(WasmValue::RefNull(ValType::RefExtern)) - } + ValType::RefFunc => val.map(WasmValue::RefFunc).unwrap_or(WasmValue::RefNull(ValType::RefFunc)), + ValType::RefExtern => val.map(WasmValue::RefExtern).unwrap_or(WasmValue::RefNull(ValType::RefExtern)), _ => unimplemented!("unsupported table type: {:?}", self.kind.element_type), }) } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index a8dd2b5..5a34eba 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20151,103,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":91,"failed":8},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":108,"failed":24},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20160,94,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":91,"failed":8},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":117,"failed":15},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index a7c27e4..6168c6d 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20140) +v0.3.0-alpha.0 (20151) - + From 0382b0660280a828498310322bfd2d50de51187a Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Tue, 23 Jan 2024 23:04:01 +0100 Subject: [PATCH 38/52] chore: support partially initialized module instances Signed-off-by: Henry Gressmann --- crates/parser/src/lib.rs | 6 ++++- crates/tinywasm/src/instance.rs | 15 +++++++++-- crates/tinywasm/src/runtime/executor/mod.rs | 17 +++++++----- crates/tinywasm/src/store.rs | 30 ++++++++++++--------- crates/tinywasm/tests/generated/mvp.csv | 2 +- 5 files changed, 48 insertions(+), 22 deletions(-) diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index ae6cc4d..aa76ea3 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -120,7 +120,11 @@ impl TryFrom for TinyWasmModule { WasmFunction { instructions: f.body, locals: f.locals, - ty: reader.func_types.get(ty_idx as usize).unwrap().clone(), + ty: reader + .func_types + .get(ty_idx as usize) + .expect("No func type for func, this is a bug") + .clone(), }, ) }) diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index d7298af..889d4f8 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -20,6 +20,8 @@ pub struct ModuleInstance(Arc); #[allow(dead_code)] #[derive(Debug)] pub(crate) struct ModuleInstanceInner { + pub(crate) failed_to_instantiate: bool, + pub(crate) store_id: usize, pub(crate) idx: ModuleInstanceAddr, @@ -69,10 +71,11 @@ impl ModuleInstance { addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?); addrs.memories.extend(store.init_memories(data.memory_types.into(), idx)?); - let elem_addrs = store.init_elements(&addrs.tables, &addrs.funcs, data.elements.into(), idx)?; - let data_addrs = store.init_datas(&addrs.memories, data.data.into(), idx)?; + let (elem_addrs, elem_trapped) = store.init_elements(&addrs.tables, &addrs.funcs, data.elements.into(), idx)?; + let (data_addrs, data_trapped) = store.init_datas(&addrs.memories, data.data.into(), idx)?; let instance = ModuleInstanceInner { + failed_to_instantiate: elem_trapped.is_some() || data_trapped.is_some(), store_id: store.id(), idx, types: data.func_types, @@ -90,6 +93,14 @@ impl ModuleInstance { let instance = ModuleInstance::new(instance); store.add_instance(instance.clone())?; + if let Some(trap) = elem_trapped { + return Err(trap.into()); + }; + + if let Some(trap) = data_trapped { + return Err(trap.into()); + }; + Ok(instance) } diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 38d59d5..4875536 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -6,7 +6,7 @@ use crate::{ runtime::{BlockType, LabelFrame}, CallFrame, Error, FuncContext, LabelArgs, ModuleInstance, Result, Store, Trap, }; -use alloc::{string::ToString, vec::Vec}; +use alloc::{format, string::ToString, vec::Vec}; use tinywasm_types::{ElementKind, Instruction, ValType}; mod macros; @@ -25,10 +25,7 @@ impl DefaultRuntime { // The function to execute, gets updated from ExecResult::Call let mut instrs = &wasm_func.instructions; - let mut current_module = store - .get_module_instance(func_inst.owner) - .expect("exec expected module instance to exist for function") - .clone(); + let mut current_module = store.get_module_instance(func_inst.owner).unwrap().clone(); while let Some(instr) = instrs.get(cf.instr_ptr) { match exec_one(&mut cf, instr, instrs, stack, store, ¤t_module)? { @@ -40,7 +37,15 @@ impl DefaultRuntime { instrs = &wasm_func.instructions; if cf.func_instance.owner != current_module.id() { - current_module.swap(store.get_module_instance(cf.func_instance.owner).unwrap().clone()); + current_module.swap( + store + .get_module_instance(cf.func_instance.owner) + .expect(&format!( + "exec expected module instance {} to exist for function", + cf.func_instance.owner + )) + .clone(), + ); } continue; diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 9bbb125..1188658 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -46,6 +46,7 @@ impl Store { /// Get a module instance by the internal id pub fn get_module_instance(&self, addr: ModuleInstanceAddr) -> Option<&ModuleInstance> { + log::debug!("existing module instances: {:?}", self.module_instances.len()); self.module_instances.get(addr as usize) } @@ -180,7 +181,7 @@ impl Store { func_addrs: &[FuncAddr], elements: Vec, idx: ModuleInstanceAddr, - ) -> Result> { + ) -> Result<(Box<[Addr]>, Option)> { let elem_count = self.data.elements.len(); let mut elem_addrs = Vec::with_capacity(elem_count); for (i, element) in elements.into_iter().enumerate() { @@ -214,15 +215,17 @@ impl Store { .copied() .ok_or_else(|| Error::Other(format!("table {} not found for element {}", table, i)))?; - // a. Let n be the length of the vector elem[i].init - // b. Execute the instruction sequence einstrs - // c. Execute the instruction i32.const 0 - // d. Execute the instruction i32.const n - // e. Execute the instruction table.init tableidx i if let Some(table) = self.data.tables.get_mut(table_addr as usize) { - table.borrow_mut().init(func_addrs, offset, &init)?; + // In wasm 2.0, it's possible to call a function that hasn't been instantiated yet, + // when using a partially initialized active element segments. + // This isn't mentioned in the spec, but the "unofficial" testsuite has a test for it: + // https://github.com/WebAssembly/testsuite/blob/5a1a590603d81f40ef471abba70a90a9ae5f4627/linking.wast#L264-L276 + // I have NO IDEA why this is allowed, but it is. + if let Err(Error::Trap(trap)) = table.borrow_mut().init(func_addrs, offset, &init) { + return Ok((elem_addrs.into_boxed_slice(), Some(trap))); + } } else { - log::error!("table {} not found", table); + return Err(Error::Other(format!("table {} not found for element {}", table, i))); } // f. Execute the instruction elm.drop i @@ -235,7 +238,7 @@ impl Store { } // this should be optimized out by the compiler - Ok(elem_addrs.into_boxed_slice()) + Ok((elem_addrs.into_boxed_slice(), None)) } /// Add data to the store, returning their addresses in the store @@ -244,7 +247,7 @@ impl Store { mem_addrs: &[MemAddr], datas: Vec, idx: ModuleInstanceAddr, - ) -> Result> { + ) -> Result<(Box<[Addr]>, Option)> { let data_count = self.data.datas.len(); let mut data_addrs = Vec::with_capacity(data_count); for (i, data) in datas.into_iter().enumerate() { @@ -268,7 +271,10 @@ impl Store { Error::Other(format!("memory {} not found for data segment {}", mem_addr, i)) })?; - mem.borrow_mut().store(offset as usize, 0, &data.data)?; + // See comment for active element sections in the function above why we need to do this here + if let Err(Error::Trap(trap)) = mem.borrow_mut().store(offset as usize, 0, &data.data) { + return Ok((data_addrs.into_boxed_slice(), Some(trap))); + } // drop the data continue; @@ -281,7 +287,7 @@ impl Store { } // this should be optimized out by the compiler - Ok(data_addrs.into_boxed_slice()) + Ok((data_addrs.into_boxed_slice(), None)) } pub(crate) fn add_global(&mut self, ty: GlobalType, value: RawWasmValue, idx: ModuleInstanceAddr) -> Result { diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 5a34eba..9ac498e 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20160,94,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":91,"failed":8},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":117,"failed":15},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20162,92,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":91,"failed":8},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":119,"failed":13},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] From ed1e181bdbefabfa7984b14e2d1383f39e0c69a4 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Wed, 24 Jan 2024 14:34:48 +0100 Subject: [PATCH 39/52] feat: linker errors Signed-off-by: Henry Gressmann --- crates/parser/src/conversion.rs | 4 +- crates/tinywasm/src/error.rs | 155 ++++++++++-------- crates/tinywasm/src/imports.rs | 86 ++++++---- .../tinywasm/src/runtime/executor/macros.rs | 4 +- crates/tinywasm/src/runtime/executor/mod.rs | 12 +- crates/types/src/lib.rs | 10 +- 6 files changed, 161 insertions(+), 110 deletions(-) diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index 1808447..90dde8c 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -70,9 +70,9 @@ pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result ImportKind::Func(ty), + wasmparser::TypeRef::Func(ty) => ImportKind::Function(ty), wasmparser::TypeRef::Table(ty) => ImportKind::Table(convert_module_table(ty)?), - wasmparser::TypeRef::Memory(ty) => ImportKind::Mem(convert_module_memory(ty)?), + wasmparser::TypeRef::Memory(ty) => ImportKind::Memory(convert_module_memory(ty)?), wasmparser::TypeRef::Global(ty) => { ImportKind::Global(GlobalType { mutable: ty.mutable, ty: convert_valtype(&ty.content_type) }) } diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index c4757a4..1d8987e 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -5,6 +5,83 @@ use tinywasm_types::FuncType; #[cfg(feature = "parser")] use tinywasm_parser::ParseError; +/// A tinywasm error +#[derive(Debug)] +pub enum Error { + #[cfg(feature = "parser")] + /// A parsing error occurred + ParseError(ParseError), + + #[cfg(feature = "std")] + /// An I/O error occurred + Io(crate::std::io::Error), + + /// A WebAssembly feature is not supported + UnsupportedFeature(String), + + /// An unknown error occurred + Other(String), + + /// A WebAssembly trap occurred + Trap(Trap), + + /// A linking error occurred + Linker(LinkingError), + + /// A function did not return a value + FuncDidNotReturn, + + /// The stack is empty + StackUnderflow, + + /// The label stack is empty + LabelStackUnderflow, + + /// An invalid label type was encountered + InvalidLabelType, + + /// The call stack is empty + CallStackEmpty, + + /// The store is not the one that the module instance was instantiated in + InvalidStore, + + /// Missing import + MissingImport { + /// The module name + module: String, + /// The import name + name: String, + }, + + /// Could not resolve an import + CouldNotResolveImport { + /// The module name + module: String, + /// The import name + name: String, + }, +} + +#[derive(Debug)] +/// A linking error +pub enum LinkingError { + /// An unknown import was encountered + UnknownImport { + /// The module name + module: String, + /// The import name + name: String, + }, + /// A mismatched import type was encountered + MismatchedImportType { + /// The module name + module: String, + /// The import name + name: String, + }, +} + #[derive(Debug)] /// A WebAssembly trap /// @@ -84,67 +161,20 @@ impl Trap { } } -#[derive(Debug)] -/// A tinywasm error -pub enum Error { - #[cfg(feature = "parser")] - /// A parsing error occurred - ParseError(ParseError), - - #[cfg(feature = "std")] - /// An I/O error occurred - Io(crate::std::io::Error), - - /// A WebAssembly feature is not supported - UnsupportedFeature(String), - - /// An unknown error occurred - Other(String), - - /// A WebAssembly trap occurred - Trap(Trap), - - /// A function did not return a value - FuncDidNotReturn, - - /// The stack is empty - StackUnderflow, - - /// The label stack is empty - LabelStackUnderflow, - - /// An invalid label type was encountered - InvalidLabelType, - - /// The call stack is empty - CallStackEmpty, - - /// The store is not the one that the module instance was instantiated in - InvalidStore, - - /// Missing import - MissingImport { - /// The module name - module: String, - /// The import name - name: String, - }, - - /// Could not resolve an import - CouldNotResolveImport { - /// The module name - module: String, - /// The import name - name: String, - }, +impl LinkingError { + /// Get the message of the linking error + pub fn message(&self) -> &'static str { + match self { + Self::UnknownImport { .. } => "unknown import", + Self::MismatchedImportType { .. } => "mismatched import type", + } + } +} - /// Invalid import type - InvalidImportType { - /// The module name - module: String, - /// The import name - name: String, - }, +impl From for Error { + fn from(value: LinkingError) -> Self { + Self::Linker(value) + } } impl From for Error { @@ -163,6 +193,7 @@ impl Display for Error { Self::Io(err) => write!(f, "I/O error: {}", err), Self::Trap(trap) => write!(f, "trap: {}", trap.message()), + Self::Linker(err) => write!(f, "linking error: {}", err.message()), Self::CallStackEmpty => write!(f, "call stack empty"), Self::InvalidLabelType => write!(f, "invalid label type"), Self::Other(message) => write!(f, "unknown error: {}", message), @@ -179,10 +210,6 @@ impl Display for Error { Self::CouldNotResolveImport { module, name } => { write!(f, "could not resolve import: {}.{}", module, name) } - - Self::InvalidImportType { module, name } => { - write!(f, "invalid import type: {}.{}", module, name) - } } } } diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index c557069..4fb466c 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -99,7 +99,7 @@ pub enum Extern { Memory(ExternMemory), /// A function - Func(Function), + Function(Function), } /// A function @@ -152,7 +152,7 @@ impl Extern { func(ctx, &args) }; - Self::Func(Function::Host(HostFunction { func: Arc::new(inner_func), ty: ty.clone() })) + Self::Function(Function::Host(HostFunction { func: Arc::new(inner_func), ty: ty.clone() })) } /// Create a new typed function import @@ -171,7 +171,7 @@ impl Extern { let ty = tinywasm_types::FuncType { params: P::val_types(), results: R::val_types() }; - Self::Func(Function::Host(HostFunction { func: Arc::new(inner_func), ty })) + Self::Function(Function::Host(HostFunction { func: Arc::new(inner_func), ty })) } pub(crate) fn kind(&self) -> ExternalKind { @@ -179,7 +179,7 @@ impl Extern { Self::Global(_) => ExternalKind::Global, Self::Table(_) => ExternalKind::Table, Self::Memory(_) => ExternalKind::Memory, - Self::Func(_) => ExternalKind::Func, + Self::Function(_) => ExternalKind::Func, } } } @@ -273,6 +273,22 @@ impl Imports { None } + fn compare_types(import: &Import, expected: &T, actual: &T) -> Result<()> + where + T: Debug + PartialEq, + { + if expected != actual { + log::error!("failed to link import {}, expected {:?}, got {:?}", import.name, expected, actual); + return Err(crate::LinkingError::MismatchedImportType { + module: import.module.to_string(), + name: import.name.to_string(), + } + .into()); + } + + Ok(()) + } + pub(crate) fn link( mut self, store: &mut crate::Store, @@ -291,46 +307,50 @@ impl Imports { match val { // A link to something that needs to be added to the store - ResolvedExtern::Extern(ex) => { - // check if the kind matches - let kind = ex.kind(); - if kind != (&import.kind).into() { - return Err(crate::Error::InvalidImportType { + ResolvedExtern::Extern(ex) => match (ex, &import.kind) { + (Extern::Global(extern_global), ImportKind::Global(ty)) => { + Self::compare_types(import, &extern_global.ty, ty)?; + imports.globals.push(store.add_global(extern_global.ty, extern_global.val.into(), idx)?); + } + (Extern::Table(extern_table), ImportKind::Table(ty)) => { + Self::compare_types(import, &extern_table.ty.element_type, &ty.element_type)?; + // TODO: do we need to check any limits? + imports.tables.push(store.add_table(extern_table.ty, idx)?); + } + (Extern::Memory(extern_memory), ImportKind::Memory(ty)) => { + Self::compare_types(import, &extern_memory.ty.arch, &ty.arch)?; + // TODO: do we need to check any limits? + imports.memories.push(store.add_mem(extern_memory.ty, idx)?); + } + (Extern::Function(extern_func), ImportKind::Function(ty)) => { + let import_func_type = module.data.func_types.get(*ty as usize).ok_or_else(|| { + crate::Error::CouldNotResolveImport { + module: import.module.to_string(), + name: import.name.to_string(), + } + })?; + + Self::compare_types(import, extern_func.ty(), import_func_type)?; + imports.funcs.push(store.add_func(extern_func, *ty, idx)?); + } + _ => { + return Err(crate::LinkingError::MismatchedImportType { module: import.module.to_string(), name: import.name.to_string(), - }); - } - - // TODO: check if the type matches - - // add it to the store and get the address - let addr = match ex { - Extern::Global(g) => store.add_global(g.ty, g.val.into(), idx)?, - Extern::Table(t) => store.add_table(t.ty, idx)?, - Extern::Memory(m) => store.add_mem(m.ty, idx)?, - Extern::Func(f) => { - let ImportKind::Func(import_type) = import.kind else { unreachable!() }; - store.add_func(f, import_type, idx)? } - }; - - // store the link - match &kind { - ExternalKind::Global => imports.globals.push(addr), - ExternalKind::Table => imports.tables.push(addr), - ExternalKind::Memory => imports.memories.push(addr), - ExternalKind::Func => imports.funcs.push(addr), + .into()); } - } + }, // A link to something already in the store ResolvedExtern::Store(val) => { // check if the kind matches if val.kind() != (&import.kind).into() { - return Err(crate::Error::InvalidImportType { + return Err(crate::LinkingError::MismatchedImportType { module: import.module.to_string(), name: import.name.to_string(), - }); + } + .into()); } // TODO: check if the type matches diff --git a/crates/tinywasm/src/runtime/executor/macros.rs b/crates/tinywasm/src/runtime/executor/macros.rs index 5b20851..909acb3 100644 --- a/crates/tinywasm/src/runtime/executor/macros.rs +++ b/crates/tinywasm/src/runtime/executor/macros.rs @@ -70,7 +70,9 @@ macro_rules! mem_store { /// Doing the actual conversion from float to int is a bit tricky, because /// we need to check for overflow. This macro generates the min/max values /// for a specific conversion, which are then used in the actual conversion. -/// Rust sadly doesn't have wrapping casts for floats (yet) +/// Rust sadly doesn't have wrapping casts for floats yet, maybe never. +/// Alternatively, https://crates.io/crates/az could be used for this but +/// it's not worth the dependency. macro_rules! float_min_max { (f32, i32) => { (-2147483904.0_f32, 2147483648.0_f32) diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 4875536..0e748de 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -6,7 +6,7 @@ use crate::{ runtime::{BlockType, LabelFrame}, CallFrame, Error, FuncContext, LabelArgs, ModuleInstance, Result, Store, Trap, }; -use alloc::{format, string::ToString, vec::Vec}; +use alloc::{string::ToString, vec::Vec}; use tinywasm_types::{ElementKind, Instruction, ValType}; mod macros; @@ -40,10 +40,12 @@ impl DefaultRuntime { current_module.swap( store .get_module_instance(cf.func_instance.owner) - .expect(&format!( - "exec expected module instance {} to exist for function", - cf.func_instance.owner - )) + .unwrap_or_else(|| { + panic!( + "exec expected module instance {} to exist for function", + cf.func_instance.owner + ) + }) .clone(), ); } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 8872479..c8e80d2 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -387,7 +387,7 @@ pub struct GlobalType { pub ty: ValType, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct TableType { pub element_type: ValType, pub size_initial: u32, @@ -443,18 +443,18 @@ pub struct Import { #[derive(Debug, Clone)] pub enum ImportKind { - Func(TypeAddr), + Function(TypeAddr), Table(TableType), - Mem(MemoryType), + Memory(MemoryType), Global(GlobalType), } impl From<&ImportKind> for ExternalKind { fn from(kind: &ImportKind) -> Self { match kind { - ImportKind::Func(_) => Self::Func, + ImportKind::Function(_) => Self::Func, ImportKind::Table(_) => Self::Table, - ImportKind::Mem(_) => Self::Memory, + ImportKind::Memory(_) => Self::Memory, ImportKind::Global(_) => Self::Global, } } From 429756600ad2b379602d1e0dc48f730cdaf823dd Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Wed, 24 Jan 2024 14:39:51 +0100 Subject: [PATCH 40/52] test: support AssertUnlinkable Signed-off-by: Henry Gressmann --- crates/tinywasm/src/error.rs | 28 +------------ crates/tinywasm/src/imports.rs | 13 ++++--- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 10 ++--- crates/tinywasm/tests/testsuite/run.rs | 39 +++++++++++++++++++ 5 files changed, 54 insertions(+), 38 deletions(-) diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index 1d8987e..aaab21e 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -45,22 +45,6 @@ pub enum Error { /// The store is not the one that the module instance was instantiated in InvalidStore, - - /// Missing import - MissingImport { - /// The module name - module: String, - /// The import name - name: String, - }, - - /// Could not resolve an import - CouldNotResolveImport { - /// The module name - module: String, - /// The import name - name: String, - }, } #[derive(Debug)] @@ -74,7 +58,7 @@ pub enum LinkingError { name: String, }, /// A mismatched import type was encountered - MismatchedImportType { + IncompatibleImportType { /// The module name module: String, /// The import name @@ -166,7 +150,7 @@ impl LinkingError { pub fn message(&self) -> &'static str { match self { Self::UnknownImport { .. } => "unknown import", - Self::MismatchedImportType { .. } => "mismatched import type", + Self::IncompatibleImportType { .. } => "incompatible import type", } } } @@ -202,14 +186,6 @@ impl Display for Error { Self::LabelStackUnderflow => write!(f, "label stack underflow"), Self::StackUnderflow => write!(f, "stack underflow"), Self::InvalidStore => write!(f, "invalid store"), - - Self::MissingImport { module, name } => { - write!(f, "missing import: {}.{}", module, name) - } - - Self::CouldNotResolveImport { module, name } => { - write!(f, "could not resolve import: {}.{}", module, name) - } } } } diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 4fb466c..6486b1d 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -279,7 +279,7 @@ impl Imports { { if expected != actual { log::error!("failed to link import {}, expected {:?}, got {:?}", import.name, expected, actual); - return Err(crate::LinkingError::MismatchedImportType { + return Err(crate::LinkingError::IncompatibleImportType { module: import.module.to_string(), name: import.name.to_string(), } @@ -299,10 +299,11 @@ impl Imports { for import in module.data.imports.iter() { let Some(val) = self.take(store, import) else { - return Err(crate::Error::MissingImport { + return Err(crate::LinkingError::UnknownImport { module: import.module.to_string(), name: import.name.to_string(), - }); + } + .into()); }; match val { @@ -324,7 +325,7 @@ impl Imports { } (Extern::Function(extern_func), ImportKind::Function(ty)) => { let import_func_type = module.data.func_types.get(*ty as usize).ok_or_else(|| { - crate::Error::CouldNotResolveImport { + crate::LinkingError::IncompatibleImportType { module: import.module.to_string(), name: import.name.to_string(), } @@ -334,7 +335,7 @@ impl Imports { imports.funcs.push(store.add_func(extern_func, *ty, idx)?); } _ => { - return Err(crate::LinkingError::MismatchedImportType { + return Err(crate::LinkingError::IncompatibleImportType { module: import.module.to_string(), name: import.name.to_string(), } @@ -346,7 +347,7 @@ impl Imports { ResolvedExtern::Store(val) => { // check if the kind matches if val.kind() != (&import.kind).into() { - return Err(crate::LinkingError::MismatchedImportType { + return Err(crate::LinkingError::IncompatibleImportType { module: import.module.to_string(), name: import.name.to_string(), } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 9ac498e..e0a5b40 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20162,92,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":91,"failed":8},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":112,"failed":71},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":119,"failed":13},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20195,59,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":91,"failed":8},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":143,"failed":40},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":121,"failed":11},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 6168c6d..3140235 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20151) +v0.3.0-alpha.0 (20195) - - - - + + + + diff --git a/crates/tinywasm/tests/testsuite/run.rs b/crates/tinywasm/tests/testsuite/run.rs index fc8977a..79d9acc 100644 --- a/crates/tinywasm/tests/testsuite/run.rs +++ b/crates/tinywasm/tests/testsuite/run.rs @@ -355,6 +355,45 @@ impl TestSuite { } } + AssertUnlinkable { mut module, span, message } => { + let res = catch_unwind_silent(|| { + let module = parse_module_bytes(&module.encode().expect("failed to encode module")) + .expect("failed to parse module"); + let module = tinywasm::Module::from(module); + module.instantiate(&mut store, Some(Self::imports(registered_modules.modules()).unwrap())) + }); + + match res { + Err(err) => test_group.add_result( + &format!("AssertUnlinkable({})", i), + span.linecol_in(wast), + Err(eyre!("test panicked: {:?}", try_downcast_panic(err))), + ), + Ok(Err(tinywasm::Error::Linker(err))) => { + if err.message() != message { + test_group.add_result( + &format!("AssertUnlinkable({})", i), + span.linecol_in(wast), + Err(eyre!("expected linker error: {}, got: {}", message, err.message())), + ); + continue; + } + + test_group.add_result(&format!("AssertUnlinkable({})", i), span.linecol_in(wast), Ok(())) + } + Ok(Err(err)) => test_group.add_result( + &format!("AssertUnlinkable({})", i), + span.linecol_in(wast), + Err(eyre!("expected linker error, {}, got: {:?}", message, err)), + ), + Ok(Ok(_)) => test_group.add_result( + &format!("AssertUnlinkable({})", i), + span.linecol_in(wast), + Err(eyre!("expected linker error {}, got Ok", message)), + ), + } + } + Invoke(invoke) => { let name = invoke.name; From 4223bb715e72c5a98ac944ee92a2aad2d6f15c7d Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Wed, 24 Jan 2024 15:02:48 +0100 Subject: [PATCH 41/52] fix: null ref element initialization Signed-off-by: Henry Gressmann --- crates/tinywasm/src/runtime/executor/mod.rs | 2 +- crates/tinywasm/src/store.rs | 42 +++++++++++++------ crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 8 ++-- crates/types/src/lib.rs | 8 ++-- 5 files changed, 39 insertions(+), 23 deletions(-) diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 0e748de..5382102 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -595,8 +595,8 @@ fn exec_one( TableSet(table_index) => { let table_idx = module.resolve_table_addr(*table_index); let table = store.get_table(table_idx as usize)?; - let idx = stack.values.pop_t::()? as usize; let val = stack.values.pop_t::()?; + let idx = stack.values.pop_t::()? as usize; table.borrow_mut().set(idx, val)?; } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 1188658..6884bf6 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -429,6 +429,8 @@ impl TableElement { } } +const MAX_TABLE_SIZE: u32 = 10000000; + /// A WebAssembly Table Instance /// /// See @@ -459,28 +461,42 @@ impl TableInstance { } pub(crate) fn set(&mut self, table_idx: usize, value: Addr) -> Result<()> { - let el = self - .elements - .get_mut(table_idx) - .ok_or_else(|| Error::Other(format!("table element {} not found", table_idx)))?; - *el = TableElement::Initialized(value); - Ok(()) + self.grow_to_fit(table_idx + 1) + .ok_or_else(|| { + Error::Trap(crate::Trap::TableOutOfBounds { offset: table_idx, len: 1, max: self.elements.len() }) + }) + .and_then(|_| { + self.elements[table_idx] = TableElement::Initialized(value); + Ok(()) + }) + } + + pub(crate) fn grow_to_fit(&mut self, new_size: usize) -> Option<()> { + if new_size > self.elements.len() { + if new_size <= self.kind.size_max.unwrap_or(MAX_TABLE_SIZE) as usize { + self.elements.resize(new_size, TableElement::Uninitialized); + } else { + return None; + } + } + Some(()) } pub(crate) fn size(&self) -> i32 { self.elements.len() as i32 } - pub(crate) fn init(&mut self, func_addrs: &[u32], offset: i32, init: &[Addr]) -> Result<()> { + pub(crate) fn init(&mut self, func_addrs: &[u32], offset: i32, init: &[Option]) -> Result<()> { let init = init .iter() - .map(|item| { - TableElement::Initialized(match self.kind.element_type == ValType::RefFunc { + .map(|item| match item { + None => TableElement::Uninitialized, + Some(item) => TableElement::Initialized(match self.kind.element_type == ValType::RefFunc { true => *func_addrs.get(*item as usize).expect( "error initializing table: function not found. This should have been caught by the validator", ), false => *item, - }) + }), }) .collect::>(); @@ -620,12 +636,12 @@ impl GlobalInstance { #[derive(Debug)] pub(crate) struct ElementInstance { pub(crate) kind: ElementKind, - pub(crate) items: Option>, // none is the element was dropped - _owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) items: Option>>, // none is the element was dropped + _owner: ModuleInstanceAddr, // index into store.module_instances } impl ElementInstance { - pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option>) -> Self { + pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option>>) -> Self { Self { kind, _owner: owner, items } } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index e0a5b40..2c063ce 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20195,59,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":91,"failed":8},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":143,"failed":40},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":121,"failed":11},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20201,53,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":97,"failed":2},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":143,"failed":40},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":121,"failed":11},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 3140235..c191896 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20195) +v0.3.0-alpha.0 (20201) - - - + + + diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index c8e80d2..9945814 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -495,11 +495,11 @@ pub enum ElementItem { } impl ElementItem { - pub fn addr(&self) -> Option { + pub fn addr(&self) -> Option> { match self { - Self::Func(addr) => Some(*addr), - Self::Expr(ConstInstruction::RefFunc(addr)) => Some(*addr), - Self::Expr(ConstInstruction::RefNull(_ty)) => Some(0), + Self::Func(addr) => Some(Some(*addr)), + Self::Expr(ConstInstruction::RefFunc(addr)) => Some(Some(*addr)), + Self::Expr(ConstInstruction::RefNull(_ty)) => Some(None), _ => None, } } From c9ecfea91a78468547398c7ec6aa19b92ccb3aea Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Wed, 24 Jan 2024 18:58:23 +0100 Subject: [PATCH 42/52] feat: const instruction global get Signed-off-by: Henry Gressmann --- crates/tinywasm/src/imports.rs | 56 +++++++---- crates/tinywasm/src/instance.rs | 7 +- crates/tinywasm/src/store.rs | 93 ++++++++++++------- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 6 +- crates/types/src/lib.rs | 11 --- 6 files changed, 107 insertions(+), 68 deletions(-) diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 6486b1d..ddca744 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -257,17 +257,7 @@ impl Imports { if let Some(addr) = self.modules.get(&name.module) { let instance = store.get_module_instance(*addr)?; - let export_addr = instance.export(&import.name)?; - - // TODO: validate kind and type - match &export_addr { - ExternVal::Global(_) => {} - ExternVal::Table(_) => {} - ExternVal::Mem(_) => {} - ExternVal::Func(_) => {} - } - - return Some(ResolvedExtern::Store(export_addr)); + return Some(ResolvedExtern::Store(instance.export(&import.name)?)); } None @@ -354,13 +344,43 @@ impl Imports { .into()); } - // TODO: check if the type matches - - match val { - ExternVal::Global(g) => imports.globals.push(g), - ExternVal::Table(t) => imports.tables.push(t), - ExternVal::Mem(m) => imports.memories.push(m), - ExternVal::Func(f) => imports.funcs.push(f), + match (val, &import.kind) { + (ExternVal::Global(global_addr), ImportKind::Global(ty)) => { + let global = store.get_global(global_addr as usize)?; + Self::compare_types(import, &global.borrow().ty, ty)?; + imports.globals.push(global_addr); + } + (ExternVal::Table(table_addr), ImportKind::Table(ty)) => { + let table = store.get_table(table_addr as usize)?; + // TODO: do we need to check any limits? + Self::compare_types(import, &table.borrow().kind.element_type, &ty.element_type)?; + imports.tables.push(table_addr); + } + (ExternVal::Mem(memory_addr), ImportKind::Memory(ty)) => { + let mem = store.get_mem(memory_addr as usize)?; + // TODO: do we need to check any limits? + Self::compare_types(import, &mem.borrow().kind.arch, &ty.arch)?; + imports.memories.push(memory_addr); + } + (ExternVal::Func(func_addr), ImportKind::Function(ty)) => { + let func = store.get_func(func_addr as usize)?; + let import_func_type = module.data.func_types.get(*ty as usize).ok_or_else(|| { + crate::LinkingError::IncompatibleImportType { + module: import.module.to_string(), + name: import.name.to_string(), + } + })?; + + Self::compare_types(import, func.func.ty(), import_func_type)?; + imports.funcs.push(func_addr); + } + _ => { + return Err(crate::LinkingError::IncompatibleImportType { + module: import.module.to_string(), + name: import.name.to_string(), + } + .into()); + } } } } diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 889d4f8..91044f5 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -66,12 +66,13 @@ impl ModuleInstance { let data = module.data; // TODO: check if the compiler correctly optimizes this to prevent wasted allocations - addrs.globals.extend(store.init_globals(data.globals.into(), idx)?); addrs.funcs.extend(store.init_funcs(data.funcs.into(), idx)?); addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?); addrs.memories.extend(store.init_memories(data.memory_types.into(), idx)?); - let (elem_addrs, elem_trapped) = store.init_elements(&addrs.tables, &addrs.funcs, data.elements.into(), idx)?; + let global_addrs = store.init_globals(addrs.globals, data.globals.into(), idx)?; + let (elem_addrs, elem_trapped) = + store.init_elements(&addrs.tables, &addrs.funcs, &global_addrs, data.elements.into(), idx)?; let (data_addrs, data_trapped) = store.init_datas(&addrs.memories, data.data.into(), idx)?; let instance = ModuleInstanceInner { @@ -82,7 +83,7 @@ impl ModuleInstance { func_addrs: addrs.funcs.into_boxed_slice(), table_addrs: addrs.tables.into_boxed_slice(), mem_addrs: addrs.memories.into_boxed_slice(), - global_addrs: addrs.globals.into_boxed_slice(), + global_addrs: global_addrs.into_boxed_slice(), elem_addrs, data_addrs, func_start: data.start_func, diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 6884bf6..40d84d5 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -158,13 +158,20 @@ impl Store { } /// Add globals to the store, returning their addresses in the store - pub(crate) fn init_globals(&mut self, globals: Vec, idx: ModuleInstanceAddr) -> Result> { + pub(crate) fn init_globals( + &mut self, + mut imported_globals: Vec, + new_globals: Vec, + idx: ModuleInstanceAddr, + ) -> Result> { let global_count = self.data.globals.len(); - let mut global_addrs = Vec::with_capacity(global_count); - for (i, global) in globals.iter().enumerate() { + imported_globals.reserve_exact(new_globals.len()); + let mut global_addrs = imported_globals; + + for (i, global) in new_globals.iter().enumerate() { self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new( global.ty, - self.eval_const(&global.init)?, + self.eval_const(&global.init, &global_addrs)?, idx, )))); global_addrs.push((i + global_count) as Addr); @@ -173,27 +180,41 @@ impl Store { Ok(global_addrs) } + fn elem_addr(&self, item: &ElementItem, globals: &[Addr]) -> Result> { + let res = match item { + ElementItem::Func(addr) => Some(*addr), + ElementItem::Expr(ConstInstruction::RefFunc(addr)) => Some(*addr), + ElementItem::Expr(ConstInstruction::RefNull(_ty)) => None, + ElementItem::Expr(ConstInstruction::GlobalGet(addr)) => { + let addr = globals.get(*addr as usize).copied().ok_or_else(|| { + Error::Other(format!("global {} not found. This should have been caught by the validator", addr)) + })?; + + let global = self.data.globals[addr as usize].clone(); + let val = global.borrow().value; + Some(val.into()) + } + _ => return Err(Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item))), + }; + + Ok(res) + } + /// Add elements to the store, returning their addresses in the store /// Should be called after the tables have been added pub(crate) fn init_elements( &mut self, table_addrs: &[TableAddr], func_addrs: &[FuncAddr], + global_addrs: &[Addr], elements: Vec, idx: ModuleInstanceAddr, ) -> Result<(Box<[Addr]>, Option)> { let elem_count = self.data.elements.len(); let mut elem_addrs = Vec::with_capacity(elem_count); for (i, element) in elements.into_iter().enumerate() { - let init = element - .items - .iter() - .map(|item| { - item.addr().ok_or_else(|| { - Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item)) - }) - }) - .collect::>>()?; + let init = + element.items.iter().map(|item| self.elem_addr(item, global_addrs)).collect::>>()?; log::error!("element kind: {:?}", element.kind); @@ -330,7 +351,11 @@ impl Store { } /// Evaluate a constant expression - pub(crate) fn eval_const(&self, const_instr: &tinywasm_types::ConstInstruction) -> Result { + pub(crate) fn eval_const( + &self, + const_instr: &tinywasm_types::ConstInstruction, + module_global_addrs: &[Addr], + ) -> Result { use tinywasm_types::ConstInstruction::*; let val = match const_instr { F32Const(f) => RawWasmValue::from(*f), @@ -338,8 +363,11 @@ impl Store { I32Const(i) => RawWasmValue::from(*i), I64Const(i) => RawWasmValue::from(*i), GlobalGet(addr) => { - let addr = *addr as usize; - let global = self.data.globals[addr].clone(); + let addr = module_global_addrs.get(*addr as usize).copied().ok_or_else(|| { + Error::Other(format!("global {} not found. This should have been caught by the validator", addr)) + })?; + + let global = self.data.globals[addr as usize].clone(); let val = global.borrow().value; val } @@ -369,8 +397,16 @@ impl Store { self.data.elements.get(addr).ok_or_else(|| Error::Other(format!("element {} not found", addr))) } + /// Get the global at the actual index in the store + pub(crate) fn get_global(&self, addr: usize) -> Result<&Rc>> { + self.data.globals.get(addr).ok_or_else(|| Error::Other(format!("global {} not found", addr))) + } + /// Get the global at the actual index in the store pub fn get_global_val(&self, addr: usize) -> Result { + log::error!("getting global: {}", addr); + log::error!("globals: {:?}", self.data.globals); + self.data .globals .get(addr) @@ -461,25 +497,18 @@ impl TableInstance { } pub(crate) fn set(&mut self, table_idx: usize, value: Addr) -> Result<()> { - self.grow_to_fit(table_idx + 1) - .ok_or_else(|| { - Error::Trap(crate::Trap::TableOutOfBounds { offset: table_idx, len: 1, max: self.elements.len() }) - }) - .and_then(|_| { - self.elements[table_idx] = TableElement::Initialized(value); - Ok(()) - }) + self.grow_to_fit(table_idx + 1).map(|_| self.elements[table_idx] = TableElement::Initialized(value)) } - pub(crate) fn grow_to_fit(&mut self, new_size: usize) -> Option<()> { + pub(crate) fn grow_to_fit(&mut self, new_size: usize) -> Result<()> { if new_size > self.elements.len() { - if new_size <= self.kind.size_max.unwrap_or(MAX_TABLE_SIZE) as usize { - self.elements.resize(new_size, TableElement::Uninitialized); - } else { - return None; + if new_size > self.kind.size_max.unwrap_or(MAX_TABLE_SIZE) as usize { + return Err(crate::Trap::TableOutOfBounds { offset: new_size, len: 1, max: self.elements.len() }.into()); } + + self.elements.resize(new_size, TableElement::Uninitialized); } - Some(()) + Ok(()) } pub(crate) fn size(&self) -> i32 { @@ -620,13 +649,13 @@ impl MemoryInstance { #[derive(Debug)] pub(crate) struct GlobalInstance { pub(crate) value: RawWasmValue, - pub(crate) _ty: GlobalType, + pub(crate) ty: GlobalType, pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances } impl GlobalInstance { pub(crate) fn new(ty: GlobalType, value: RawWasmValue, owner: ModuleInstanceAddr) -> Self { - Self { _ty: ty, value, _owner: owner } + Self { ty, value, _owner: owner } } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 2c063ce..c173318 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20201,53,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":97,"failed":2},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":143,"failed":40},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":121,"failed":11},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20241,13,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":1},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":171,"failed":12},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index c191896..2c9591c 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20201) +v0.3.0-alpha.0 (20240) - + + - diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 9945814..a467d7a 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -493,14 +493,3 @@ pub enum ElementItem { Func(FuncAddr), Expr(ConstInstruction), } - -impl ElementItem { - pub fn addr(&self) -> Option> { - match self { - Self::Func(addr) => Some(Some(*addr)), - Self::Expr(ConstInstruction::RefFunc(addr)) => Some(Some(*addr)), - Self::Expr(ConstInstruction::RefNull(_ty)) => Some(None), - _ => None, - } - } -} From 4501b9bf494c2a3b91076abdf338d1c01117b4ba Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Wed, 24 Jan 2024 19:04:34 +0100 Subject: [PATCH 43/52] test: add 2.0 testsuite Signed-off-by: Henry Gressmann --- .cargo/config.toml | 1 + crates/tinywasm/Cargo.toml | 4 ++++ crates/tinywasm/tests/generated/2.0.csv | 1 + crates/tinywasm/tests/test-two.rs | 29 +++++++++++++++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 crates/tinywasm/tests/generated/2.0.csv create mode 100644 crates/tinywasm/tests/test-two.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 7ccfd76..19d47a2 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,6 +3,7 @@ version-dev="workspaces version --no-git-commit --force tinywasm*" dev="run -- -l debug run" test-mvp="test --package tinywasm --test test-mvp --release -- --enable " +test-2="test --package tinywasm --test test-two --release -- --enable " test-wast="test --package tinywasm --test test-wast -- --enable " test-wast-release="test --package tinywasm --test test-wast --release -- --enable " generate-charts="test --package tinywasm --test generate-charts -- --enable " diff --git a/crates/tinywasm/Cargo.toml b/crates/tinywasm/Cargo.toml index 7063f4c..9e336c8 100644 --- a/crates/tinywasm/Cargo.toml +++ b/crates/tinywasm/Cargo.toml @@ -41,6 +41,10 @@ harness=false name="test-mvp" harness=false +[[test]] +name="test-two" +harness=false + [[test]] name="test-wast" harness=false diff --git a/crates/tinywasm/tests/generated/2.0.csv b/crates/tinywasm/tests/generated/2.0.csv new file mode 100644 index 0000000..cd65c38 --- /dev/null +++ b/crates/tinywasm/tests/generated/2.0.csv @@ -0,0 +1 @@ +0.3.0-alpha.0,26722,1161,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"bulk.wast","passed":8,"failed":109},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":1},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":171,"failed":12},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_copy.wast","passed":3928,"failed":522},{"name":"memory_fill.wast","passed":64,"failed":36},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_init.wast","passed":177,"failed":63},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"ref_func.wast","passed":9,"failed":8},{"name":"ref_is_null.wast","passed":4,"failed":12},{"name":"ref_null.wast","passed":1,"failed":2},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"table_copy.wast","passed":1613,"failed":115},{"name":"table_fill.wast","passed":23,"failed":22},{"name":"table_get.wast","passed":10,"failed":6},{"name":"table_grow.wast","passed":21,"failed":29},{"name":"table_init.wast","passed":594,"failed":186},{"name":"table_set.wast","passed":19,"failed":7},{"name":"table_size.wast","passed":8,"failed":31},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/test-two.rs b/crates/tinywasm/tests/test-two.rs new file mode 100644 index 0000000..e710d1a --- /dev/null +++ b/crates/tinywasm/tests/test-two.rs @@ -0,0 +1,29 @@ +mod testsuite; +use eyre::{eyre, Result}; +use owo_colors::OwoColorize; +use testsuite::TestSuite; + +fn main() -> Result<()> { + let args = std::env::args().collect::>(); + if args.len() < 2 || args[1] != "--enable" { + return Ok(()); + } + + test_2() +} + +fn test_2() -> Result<()> { + let mut test_suite = TestSuite::new(); + + TestSuite::set_log_level(log::LevelFilter::Off); + test_suite.run_spec_group(wasm_testsuite::V2_DRAFT_1_TESTS)?; + test_suite.save_csv("./tests/generated/2.0.csv", env!("CARGO_PKG_VERSION"))?; + + if test_suite.failed() { + println!(); + Err(eyre!(format!("{}:\n{:#?}", "failed one or more tests".red().bold(), test_suite,))) + } else { + println!("\n\npassed all tests:\n{:#?}", test_suite); + Ok(()) + } +} From be0c5aa8ec4dcb9bd595edfc83b979aa40d6ae5d Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Wed, 24 Jan 2024 19:40:29 +0100 Subject: [PATCH 44/52] chore: import should error on invalid memory/table type Signed-off-by: Henry Gressmann --- crates/tinywasm/src/error.rs | 8 +- crates/tinywasm/src/imports.rs | 88 ++++++++++++++++--- crates/tinywasm/src/runtime/executor/mod.rs | 4 +- crates/tinywasm/src/store.rs | 14 ++- crates/tinywasm/tests/generated/mvp.csv | 2 +- .../tinywasm/tests/generated/progress-mvp.svg | 6 +- 6 files changed, 93 insertions(+), 29 deletions(-) diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index aaab21e..22dae60 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -1,4 +1,4 @@ -use alloc::string::String; +use alloc::string::{String, ToString}; use core::fmt::Display; use tinywasm_types::FuncType; @@ -66,6 +66,12 @@ pub enum LinkingError { }, } +impl LinkingError { + pub(crate) fn incompatible_import_type(import: &tinywasm_types::Import) -> Self { + Self::IncompatibleImportType { module: import.module.to_string(), name: import.name.to_string() } + } +} + #[derive(Debug)] /// A WebAssembly trap /// diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index ddca744..f9c5cda 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -4,7 +4,7 @@ use core::fmt::Debug; use crate::{ func::{FromWasmValueTuple, IntoWasmValueTuple, ValTypesFromTuple}, - Result, + LinkingError, Result, }; use alloc::{ collections::BTreeMap, @@ -263,19 +263,79 @@ impl Imports { None } - fn compare_types(import: &Import, expected: &T, actual: &T) -> Result<()> + fn compare_types(import: &Import, actual: &T, expected: &T) -> Result<()> where T: Debug + PartialEq, { if expected != actual { log::error!("failed to link import {}, expected {:?}, got {:?}", import.name, expected, actual); - return Err(crate::LinkingError::IncompatibleImportType { - module: import.module.to_string(), - name: import.name.to_string(), + return Err(LinkingError::incompatible_import_type(import).into()); + } + + Ok(()) + } + + fn compare_table_types(import: &Import, expected: &TableType, actual: &TableType) -> Result<()> { + Self::compare_types(import, &actual.element_type, &expected.element_type)?; + + if actual.size_initial > expected.size_initial { + return Err(LinkingError::incompatible_import_type(import).into()); + } + + match (expected.size_max, actual.size_max) { + (None, Some(_)) => return Err(LinkingError::incompatible_import_type(import).into()), + (Some(expected_max), Some(actual_max)) if actual_max < expected_max => { + return Err(LinkingError::incompatible_import_type(import).into()) + } + _ => {} + } + + // if expected.size_max.is_none() && actual.size_max.is_some() { + // return Err(LinkingError::incompatible_import_type(import).into()); + // } + + // if expected.size_max.unwrap_or(0) < actual.size_max.unwrap_or(0) { + // return Err(LinkingError::incompatible_import_type(import).into()); + // } + + log::error!("size_initial: expected: {:?} got: {:?}", expected.size_initial, actual.size_initial); + log::error!("size_max: expected: {:?} got: {:?}", expected.size_max, actual.size_max); + // TODO: check limits + + Ok(()) + } + + fn compare_memory_types( + import: &Import, + expected: &MemoryType, + actual: &MemoryType, + real_size: Option, + ) -> Result<()> { + Self::compare_types(import, &expected.arch, &actual.arch)?; + + if actual.page_count_initial > expected.page_count_initial { + if let Some(real_size) = real_size { + if actual.page_count_initial > real_size as u64 { + return Err(LinkingError::incompatible_import_type(import).into()); + } + } else { + return Err(LinkingError::incompatible_import_type(import).into()); + } + } + + match (expected.page_count_max, actual.page_count_max) { + (None, Some(_)) => return Err(LinkingError::incompatible_import_type(import).into()), + (Some(expected_max), Some(actual_max)) if actual_max < expected_max => { + return Err(LinkingError::incompatible_import_type(import).into()) } - .into()); + _ => {} } + log::error!("size_initial: {:?} {:?}", expected.page_count_initial, actual.page_count_initial); + log::error!("size_max: {:?} {:?}", expected.page_count_max, actual.page_count_max); + + // TODO: check limits + Ok(()) } @@ -304,13 +364,11 @@ impl Imports { imports.globals.push(store.add_global(extern_global.ty, extern_global.val.into(), idx)?); } (Extern::Table(extern_table), ImportKind::Table(ty)) => { - Self::compare_types(import, &extern_table.ty.element_type, &ty.element_type)?; - // TODO: do we need to check any limits? + Self::compare_table_types(import, &extern_table.ty, &ty)?; imports.tables.push(store.add_table(extern_table.ty, idx)?); } (Extern::Memory(extern_memory), ImportKind::Memory(ty)) => { - Self::compare_types(import, &extern_memory.ty.arch, &ty.arch)?; - // TODO: do we need to check any limits? + Self::compare_memory_types(import, &extern_memory.ty, &ty, None)?; imports.memories.push(store.add_mem(extern_memory.ty, idx)?); } (Extern::Function(extern_func), ImportKind::Function(ty)) => { @@ -352,14 +410,16 @@ impl Imports { } (ExternVal::Table(table_addr), ImportKind::Table(ty)) => { let table = store.get_table(table_addr as usize)?; - // TODO: do we need to check any limits? - Self::compare_types(import, &table.borrow().kind.element_type, &ty.element_type)?; + Self::compare_table_types(import, &table.borrow().kind, &ty)?; imports.tables.push(table_addr); } (ExternVal::Mem(memory_addr), ImportKind::Memory(ty)) => { let mem = store.get_mem(memory_addr as usize)?; - // TODO: do we need to check any limits? - Self::compare_types(import, &mem.borrow().kind.arch, &ty.arch)?; + let (size, kind) = { + let mem = mem.borrow(); + (mem.page_count(), mem.kind.clone()) + }; + Self::compare_memory_types(import, &kind, &ty, Some(size))?; imports.memories.push(memory_addr); } (ExternVal::Func(func_addr), ImportKind::Function(ty)) => { diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index 5382102..aa52923 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -385,7 +385,7 @@ fn exec_one( let mem_idx = module.resolve_mem_addr(*addr); let mem = store.get_mem(mem_idx as usize)?; - stack.values.push(mem.borrow().size().into()); + stack.values.push((mem.borrow().page_count() as i32).into()); } MemoryGrow(addr, byte) => { @@ -398,7 +398,7 @@ fn exec_one( let (res, prev_size) = { let mut mem = mem.borrow_mut(); - let prev_size = mem.size(); + let prev_size = mem.page_count() as i32; (mem.grow(stack.values.pop_t::()?), prev_size) }; diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 40d84d5..6144597 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -607,17 +607,15 @@ impl MemoryInstance { Ok(&self.data[addr..end]) } - pub(crate) fn size(&self) -> i32 { - log::debug!("memory pages: {}", self.page_count); - log::debug!("memory size: {}", self.page_count * PAGE_SIZE); - self.page_count as i32 + pub(crate) fn page_count(&self) -> usize { + self.page_count } pub(crate) fn grow(&mut self, delta: i32) -> Option { - let current_pages = self.size(); - let new_pages = current_pages + delta; + let current_pages = self.page_count(); + let new_pages = current_pages as i64 + delta as i64; - if new_pages < 0 || new_pages > MAX_PAGES as i32 { + if new_pages < 0 || new_pages > MAX_PAGES as i64 { return None; } @@ -639,7 +637,7 @@ impl MemoryInstance { log::debug!("memory grown by {} pages", delta); log::debug!("memory grown to {} pages", self.page_count); - Some(current_pages) + Some(current_pages.try_into().expect("memory size out of bounds, this should have been caught earlier")) } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index c173318..df4ec19 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20241,13,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":1},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":171,"failed":12},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20253,1,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":1},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index 2c9591c..e168cb9 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20240) +v0.3.0-alpha.0 (20253) - + + - From 64ed1bf86950c52e3400c0a536e223a53f48a4b7 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 25 Jan 2024 01:01:25 +0100 Subject: [PATCH 45/52] feat: pass full wasm 1.0 testsuite Signed-off-by: Henry Gressmann --- .github/workflows/test.yaml | 6 ++ crates/cli/src/args.rs | 27 ++---- crates/cli/src/bin.rs | 7 +- crates/parser/src/error.rs | 5 +- crates/tinywasm/src/error.rs | 4 + crates/tinywasm/src/func.rs | 2 - crates/tinywasm/src/imports.rs | 81 ++++------------ crates/tinywasm/src/instance.rs | 2 +- crates/tinywasm/src/runtime/executor/mod.rs | 6 -- crates/tinywasm/src/runtime/stack/blocks.rs | 7 +- crates/tinywasm/src/store.rs | 101 +++++++++++++------- crates/tinywasm/tests/generated/mvp.csv | 2 +- crates/tinywasm/tests/testsuite/indexmap.rs | 5 +- 13 files changed, 111 insertions(+), 144 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 0baaba9..24d4277 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -27,6 +27,9 @@ jobs: - name: Run tests (stable) run: cargo +stable test --workspace --exclude wasm-testsuite + - name: Run MVP testsuite + run: cargo +stable test-mvp + test-no-std: name: Test without default features on nightly Rust runs-on: ubuntu-latest @@ -43,3 +46,6 @@ jobs: - name: Run tests (nightly, no default features) run: cargo +nightly test --workspace --exclude wasm-testsuite --no-default-features + + - name: Run MVP testsuite (nightly) + run: cargo +nightly test-mvp diff --git a/crates/cli/src/args.rs b/crates/cli/src/args.rs index 379ecf8..3959572 100644 --- a/crates/cli/src/args.rs +++ b/crates/cli/src/args.rs @@ -17,29 +17,14 @@ impl From for WasmValue { impl FromStr for WasmArg { type Err = String; fn from_str(s: &str) -> std::prelude::v1::Result { - let [ty, val]: [&str; 2] = s - .split(':') - .collect::>() - .try_into() - .map_err(|e| format!("invalid arguments: {:?}", e))?; + let [ty, val]: [&str; 2] = + s.split(':').collect::>().try_into().map_err(|e| format!("invalid arguments: {:?}", e))?; let arg: WasmValue = match ty { - "i32" => val - .parse::() - .map_err(|e| format!("invalid argument value for i32: {e:?}"))? - .into(), - "i64" => val - .parse::() - .map_err(|e| format!("invalid argument value for i64: {e:?}"))? - .into(), - "f32" => val - .parse::() - .map_err(|e| format!("invalid argument value for f32: {e:?}"))? - .into(), - "f64" => val - .parse::() - .map_err(|e| format!("invalid argument value for f64: {e:?}"))? - .into(), + "i32" => val.parse::().map_err(|e| format!("invalid argument value for i32: {e:?}"))?.into(), + "i64" => val.parse::().map_err(|e| format!("invalid argument value for i64: {e:?}"))?.into(), + "f32" => val.parse::().map_err(|e| format!("invalid argument value for f32: {e:?}"))?.into(), + "f64" => val.parse::().map_err(|e| format!("invalid argument value for f64: {e:?}"))?.into(), t => return Err(format!("Invalid arg type: {}", t)), }; diff --git a/crates/cli/src/bin.rs b/crates/cli/src/bin.rs index c8ab379..1c166cf 100644 --- a/crates/cli/src/bin.rs +++ b/crates/cli/src/bin.rs @@ -84,12 +84,7 @@ fn main() -> Result<()> { let cwd = std::env::current_dir()?; match args.nested { - TinyWasmSubcommand::Run(Run { - wasm_file, - engine, - args, - func, - }) => { + TinyWasmSubcommand::Run(Run { wasm_file, engine, args, func }) => { debug!("args: {:?}", args); let path = cwd.join(wasm_file.clone()); diff --git a/crates/parser/src/error.rs b/crates/parser/src/error.rs index acacfa0..714535a 100644 --- a/crates/parser/src/error.rs +++ b/crates/parser/src/error.rs @@ -43,10 +43,7 @@ impl crate::std::error::Error for ParseError {} impl From for ParseError { fn from(value: wasmparser::BinaryReaderError) -> Self { - Self::ParseError { - message: value.message().to_string(), - offset: value.offset(), - } + Self::ParseError { message: value.message().to_string(), offset: value.offset() } } } diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index 22dae60..f9b41be 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -70,6 +70,10 @@ impl LinkingError { pub(crate) fn incompatible_import_type(import: &tinywasm_types::Import) -> Self { Self::IncompatibleImportType { module: import.module.to_string(), name: import.name.to_string() } } + + pub(crate) fn unknown_import(import: &tinywasm_types::Import) -> Self { + Self::UnknownImport { module: import.module.to_string(), name: import.name.to_string() } + } } #[derive(Debug)] diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 8518af0..19d1325 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -168,8 +168,6 @@ macro_rules! impl_from_wasm_value_tuple { #[allow(unused_variables, unused_mut)] let mut iter = values.into_iter(); - log::error!("from_wasm_value_tuple: {:?}", iter); - Ok(( $( $T::try_from( diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index f9c5cda..804aa12 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -162,10 +162,8 @@ impl Extern { R: IntoWasmValueTuple + ValTypesFromTuple + Debug, { let inner_func = move |ctx: FuncContext<'_>, args: &[WasmValue]| -> Result> { - log::error!("args: {:?}", args); let args = P::from_wasm_value_tuple(args.to_vec())?; let result = func(ctx, args)?; - log::error!("result: {:?}", result); Ok(result.into_wasm_value_tuple()) }; @@ -290,18 +288,6 @@ impl Imports { _ => {} } - // if expected.size_max.is_none() && actual.size_max.is_some() { - // return Err(LinkingError::incompatible_import_type(import).into()); - // } - - // if expected.size_max.unwrap_or(0) < actual.size_max.unwrap_or(0) { - // return Err(LinkingError::incompatible_import_type(import).into()); - // } - - log::error!("size_initial: expected: {:?} got: {:?}", expected.size_initial, actual.size_initial); - log::error!("size_max: expected: {:?} got: {:?}", expected.size_max, actual.size_max); - // TODO: check limits - Ok(()) } @@ -331,11 +317,6 @@ impl Imports { _ => {} } - log::error!("size_initial: {:?} {:?}", expected.page_count_initial, actual.page_count_initial); - log::error!("size_max: {:?} {:?}", expected.page_count_max, actual.page_count_max); - - // TODO: check limits - Ok(()) } @@ -348,13 +329,7 @@ impl Imports { let mut imports = ResolvedImports::new(); for import in module.data.imports.iter() { - let Some(val) = self.take(store, import) else { - return Err(crate::LinkingError::UnknownImport { - module: import.module.to_string(), - name: import.name.to_string(), - } - .into()); - }; + let val = self.take(store, import).ok_or_else(|| LinkingError::unknown_import(import))?; match val { // A link to something that needs to be added to the store @@ -364,42 +339,31 @@ impl Imports { imports.globals.push(store.add_global(extern_global.ty, extern_global.val.into(), idx)?); } (Extern::Table(extern_table), ImportKind::Table(ty)) => { - Self::compare_table_types(import, &extern_table.ty, &ty)?; + Self::compare_table_types(import, &extern_table.ty, ty)?; imports.tables.push(store.add_table(extern_table.ty, idx)?); } (Extern::Memory(extern_memory), ImportKind::Memory(ty)) => { - Self::compare_memory_types(import, &extern_memory.ty, &ty, None)?; + Self::compare_memory_types(import, &extern_memory.ty, ty, None)?; imports.memories.push(store.add_mem(extern_memory.ty, idx)?); } (Extern::Function(extern_func), ImportKind::Function(ty)) => { - let import_func_type = module.data.func_types.get(*ty as usize).ok_or_else(|| { - crate::LinkingError::IncompatibleImportType { - module: import.module.to_string(), - name: import.name.to_string(), - } - })?; + let import_func_type = module + .data + .func_types + .get(*ty as usize) + .ok_or_else(|| LinkingError::incompatible_import_type(import))?; Self::compare_types(import, extern_func.ty(), import_func_type)?; imports.funcs.push(store.add_func(extern_func, *ty, idx)?); } - _ => { - return Err(crate::LinkingError::IncompatibleImportType { - module: import.module.to_string(), - name: import.name.to_string(), - } - .into()); - } + _ => return Err(LinkingError::incompatible_import_type(import).into()), }, // A link to something already in the store ResolvedExtern::Store(val) => { // check if the kind matches if val.kind() != (&import.kind).into() { - return Err(crate::LinkingError::IncompatibleImportType { - module: import.module.to_string(), - name: import.name.to_string(), - } - .into()); + return Err(LinkingError::incompatible_import_type(import).into()); } match (val, &import.kind) { @@ -410,37 +374,30 @@ impl Imports { } (ExternVal::Table(table_addr), ImportKind::Table(ty)) => { let table = store.get_table(table_addr as usize)?; - Self::compare_table_types(import, &table.borrow().kind, &ty)?; + Self::compare_table_types(import, &table.borrow().kind, ty)?; imports.tables.push(table_addr); } (ExternVal::Mem(memory_addr), ImportKind::Memory(ty)) => { let mem = store.get_mem(memory_addr as usize)?; let (size, kind) = { let mem = mem.borrow(); - (mem.page_count(), mem.kind.clone()) + (mem.page_count(), mem.kind) }; - Self::compare_memory_types(import, &kind, &ty, Some(size))?; + Self::compare_memory_types(import, &kind, ty, Some(size))?; imports.memories.push(memory_addr); } (ExternVal::Func(func_addr), ImportKind::Function(ty)) => { let func = store.get_func(func_addr as usize)?; - let import_func_type = module.data.func_types.get(*ty as usize).ok_or_else(|| { - crate::LinkingError::IncompatibleImportType { - module: import.module.to_string(), - name: import.name.to_string(), - } - })?; + let import_func_type = module + .data + .func_types + .get(*ty as usize) + .ok_or_else(|| LinkingError::incompatible_import_type(import))?; Self::compare_types(import, func.func.ty(), import_func_type)?; imports.funcs.push(func_addr); } - _ => { - return Err(crate::LinkingError::IncompatibleImportType { - module: import.module.to_string(), - name: import.name.to_string(), - } - .into()); - } + _ => return Err(LinkingError::incompatible_import_type(import).into()), } } } diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 91044f5..d1fbd6f 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -70,7 +70,7 @@ impl ModuleInstance { addrs.tables.extend(store.init_tables(data.table_types.into(), idx)?); addrs.memories.extend(store.init_memories(data.memory_types.into(), idx)?); - let global_addrs = store.init_globals(addrs.globals, data.globals.into(), idx)?; + let global_addrs = store.init_globals(addrs.globals, data.globals.into(), &addrs.funcs, idx)?; let (elem_addrs, elem_trapped) = store.init_elements(&addrs.tables, &addrs.funcs, &global_addrs, data.elements.into(), idx)?; let (data_addrs, data_trapped) = store.init_datas(&addrs.memories, data.data.into(), idx)?; diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/executor/mod.rs index aa52923..d0f011f 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/executor/mod.rs @@ -139,7 +139,6 @@ fn exec_one( } Call(v) => { - log::info!("start call"); // prepare the call frame let func_idx = module.resolve_func_addr(*v); let func_inst = store.get_func(func_idx as usize)?.clone(); @@ -148,9 +147,7 @@ fn exec_one( crate::Function::Wasm(ref f) => (f.locals.to_vec(), f.ty.clone()), crate::Function::Host(host_func) => { let func = host_func.func.clone(); - log::info!("Getting params: {:?}", host_func.ty.params); let params = stack.values.pop_params(&host_func.ty.params)?; - log::error!("Calling host function, params: {:?}", params); let res = (func)(FuncContext { store, module }, ¶ms)?; stack.values.extend_from_typed(&res); return Ok(ExecResult::Ok); @@ -158,9 +155,6 @@ fn exec_one( }; let params = stack.values.pop_n_rev(ty.params.len())?; - log::info!("call: current fn owner: {:?}", module.id()); - log::info!("call: func owner: {:?}", func_inst.owner); - let call_frame = CallFrame::new_raw(func_inst, ¶ms, locals); // push the call frame diff --git a/crates/tinywasm/src/runtime/stack/blocks.rs b/crates/tinywasm/src/runtime/stack/blocks.rs index f5a0d8d..76252b5 100644 --- a/crates/tinywasm/src/runtime/stack/blocks.rs +++ b/crates/tinywasm/src/runtime/stack/blocks.rs @@ -72,10 +72,9 @@ impl LabelArgs { Ok(match args { BlockArgs::Empty => LabelArgs { params: 0, results: 0 }, BlockArgs::Type(_) => LabelArgs { params: 0, results: 1 }, - BlockArgs::FuncType(t) => LabelArgs { - params: module.func_ty(t).params.len(), - results: module.func_ty(t).results.len(), - }, + BlockArgs::FuncType(t) => { + LabelArgs { params: module.func_ty(t).params.len(), results: module.func_ty(t).results.len() } + } }) } } diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index 6144597..aabbf71 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -162,6 +162,7 @@ impl Store { &mut self, mut imported_globals: Vec, new_globals: Vec, + func_addrs: &[FuncAddr], idx: ModuleInstanceAddr, ) -> Result> { let global_count = self.data.globals.len(); @@ -171,7 +172,7 @@ impl Store { for (i, global) in new_globals.iter().enumerate() { self.data.globals.push(Rc::new(RefCell::new(GlobalInstance::new( global.ty, - self.eval_const(&global.init, &global_addrs)?, + self.eval_const(&global.init, &global_addrs, func_addrs)?, idx, )))); global_addrs.push((i + global_count) as Addr); @@ -180,10 +181,13 @@ impl Store { Ok(global_addrs) } - fn elem_addr(&self, item: &ElementItem, globals: &[Addr]) -> Result> { + fn elem_addr(&self, item: &ElementItem, globals: &[Addr], funcs: &[FuncAddr]) -> Result> { let res = match item { - ElementItem::Func(addr) => Some(*addr), - ElementItem::Expr(ConstInstruction::RefFunc(addr)) => Some(*addr), + ElementItem::Func(addr) | ElementItem::Expr(ConstInstruction::RefFunc(addr)) => { + Some(funcs.get(*addr as usize).copied().ok_or_else(|| { + Error::Other(format!("function {} not found. This should have been caught by the validator", addr)) + })?) + } ElementItem::Expr(ConstInstruction::RefNull(_ty)) => None, ElementItem::Expr(ConstInstruction::GlobalGet(addr)) => { let addr = globals.get(*addr as usize).copied().ok_or_else(|| { @@ -191,8 +195,14 @@ impl Store { })?; let global = self.data.globals[addr as usize].clone(); - let val = global.borrow().value; - Some(val.into()) + let val = i64::from(global.borrow().value); + log::error!("global: {}", val); + if val < 0 { + // the global is actually a null reference + None + } else { + Some(val as u32) + } } _ => return Err(Error::UnsupportedFeature(format!("const expression other than ref: {:?}", item))), }; @@ -213,8 +223,11 @@ impl Store { let elem_count = self.data.elements.len(); let mut elem_addrs = Vec::with_capacity(elem_count); for (i, element) in elements.into_iter().enumerate() { - let init = - element.items.iter().map(|item| self.elem_addr(item, global_addrs)).collect::>>()?; + let init = element + .items + .iter() + .map(|item| Ok(TableElement::from(self.elem_addr(item, global_addrs, func_addrs)?))) + .collect::>>()?; log::error!("element kind: {:?}", element.kind); @@ -242,7 +255,7 @@ impl Store { // This isn't mentioned in the spec, but the "unofficial" testsuite has a test for it: // https://github.com/WebAssembly/testsuite/blob/5a1a590603d81f40ef471abba70a90a9ae5f4627/linking.wast#L264-L276 // I have NO IDEA why this is allowed, but it is. - if let Err(Error::Trap(trap)) = table.borrow_mut().init(func_addrs, offset, &init) { + if let Err(Error::Trap(trap)) = table.borrow_mut().init_raw(offset, &init) { return Ok((elem_addrs.into_boxed_slice(), Some(trap))); } } else { @@ -355,6 +368,7 @@ impl Store { &self, const_instr: &tinywasm_types::ConstInstruction, module_global_addrs: &[Addr], + module_func_addrs: &[FuncAddr], ) -> Result { use tinywasm_types::ConstInstruction::*; let val = match const_instr { @@ -367,12 +381,15 @@ impl Store { Error::Other(format!("global {} not found. This should have been caught by the validator", addr)) })?; - let global = self.data.globals[addr as usize].clone(); - let val = global.borrow().value; - val + let global = + self.data.globals.get(addr as usize).expect("global not found. This should be unreachable"); + + global.borrow().value } RefNull(t) => RawWasmValue::from(t.default_value()), - RefFunc(idx) => RawWasmValue::from(*idx as i64), + RefFunc(idx) => RawWasmValue::from(module_func_addrs.get(*idx as usize).copied().ok_or_else(|| { + Error::Other(format!("function {} not found. This should have been caught by the validator", idx)) + })?), }; Ok(val) } @@ -404,9 +421,6 @@ impl Store { /// Get the global at the actual index in the store pub fn get_global_val(&self, addr: usize) -> Result { - log::error!("getting global: {}", addr); - log::error!("globals: {:?}", self.data.globals); - self.data .globals .get(addr) @@ -456,6 +470,15 @@ pub(crate) enum TableElement { Initialized(Addr), } +impl From> for TableElement { + fn from(addr: Option) -> Self { + match addr { + None => TableElement::Uninitialized, + Some(addr) => TableElement::Initialized(addr), + } + } +} + impl TableElement { pub(crate) fn addr(&self) -> Option { match self { @@ -463,6 +486,13 @@ impl TableElement { TableElement::Initialized(addr) => Some(*addr), } } + + pub(crate) fn map Addr>(self, f: F) -> Self { + match self { + TableElement::Uninitialized => TableElement::Uninitialized, + TableElement::Initialized(addr) => TableElement::Initialized(f(addr)), + } + } } const MAX_TABLE_SIZE: u32 = 10000000; @@ -515,20 +545,18 @@ impl TableInstance { self.elements.len() as i32 } - pub(crate) fn init(&mut self, func_addrs: &[u32], offset: i32, init: &[Option]) -> Result<()> { - let init = init - .iter() - .map(|item| match item { - None => TableElement::Uninitialized, - Some(item) => TableElement::Initialized(match self.kind.element_type == ValType::RefFunc { - true => *func_addrs.get(*item as usize).expect( - "error initializing table: function not found. This should have been caught by the validator", - ), - false => *item, - }), - }) - .collect::>(); + fn resolve_func_ref(&self, func_addrs: &[u32], addr: Addr) -> Addr { + if self.kind.element_type != ValType::RefFunc { + return addr; + } + *func_addrs + .get(addr as usize) + .expect("error initializing table: function not found. This should have been caught by the validator") + } + + // Initialize the table with the given elements + pub(crate) fn init_raw(&mut self, offset: i32, init: &[TableElement]) -> Result<()> { let offset = offset as usize; let end = offset.checked_add(init.len()).ok_or_else(|| { Error::Trap(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() }) @@ -538,10 +566,17 @@ impl TableInstance { return Err(crate::Trap::TableOutOfBounds { offset, len: init.len(), max: self.elements.len() }.into()); } - self.elements[offset..end].copy_from_slice(&init); + self.elements[offset..end].copy_from_slice(init); log::debug!("table: {:?}", self.elements); Ok(()) } + + // Initialize the table with the given elements (resolves function references) + pub(crate) fn init(&mut self, func_addrs: &[u32], offset: i32, init: &[TableElement]) -> Result<()> { + let init = init.iter().map(|item| item.map(|addr| self.resolve_func_ref(func_addrs, addr))).collect::>(); + + self.init_raw(offset, &init) + } } pub(crate) const PAGE_SIZE: usize = 65536; @@ -663,12 +698,12 @@ impl GlobalInstance { #[derive(Debug)] pub(crate) struct ElementInstance { pub(crate) kind: ElementKind, - pub(crate) items: Option>>, // none is the element was dropped - _owner: ModuleInstanceAddr, // index into store.module_instances + pub(crate) items: Option>, // none is the element was dropped + _owner: ModuleInstanceAddr, // index into store.module_instances } impl ElementInstance { - pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option>>) -> Self { + pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option>) -> Self { Self { kind, _owner: owner, items } } } diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index df4ec19..7e16714 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20253,1,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":1},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20254,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":99,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/testsuite/indexmap.rs b/crates/tinywasm/tests/testsuite/indexmap.rs index d4e3869..1642ce2 100644 --- a/crates/tinywasm/tests/testsuite/indexmap.rs +++ b/crates/tinywasm/tests/testsuite/indexmap.rs @@ -8,10 +8,7 @@ where K: std::cmp::Eq + std::hash::Hash + Clone, { pub fn new() -> Self { - Self { - map: std::collections::HashMap::new(), - keys: Vec::new(), - } + Self { map: std::collections::HashMap::new(), keys: Vec::new() } } pub fn insert(&mut self, key: K, value: V) -> Option { From 00ac90357bbd256436846beceba67b38d4743bf6 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 25 Jan 2024 12:43:15 +0100 Subject: [PATCH 46/52] fix: ci Signed-off-by: Henry Gressmann --- .github/workflows/test.yaml | 11 +++++------ crates/tinywasm/tests/generated/2.0.csv | 3 ++- crates/tinywasm/tests/generated/mvp.csv | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 24d4277..2631077 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -17,9 +17,7 @@ jobs: submodules: true - name: Install stable Rust toolchain - run: | - rustup toolchain install stable - rustup default stable + run: rustup update stable - name: Build (stable) run: cargo +stable build --workspace --exclude wasm-testsuite @@ -36,10 +34,11 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true + - name: Install nightly Rust toolchain - run: | - rustup toolchain install nightly - rustup default nightly + run: rustup update stable nightly - name: Build (nightly, no default features) run: cargo +nightly build --workspace --exclude wasm-testsuite --no-default-features diff --git a/crates/tinywasm/tests/generated/2.0.csv b/crates/tinywasm/tests/generated/2.0.csv index cd65c38..0d233ee 100644 --- a/crates/tinywasm/tests/generated/2.0.csv +++ b/crates/tinywasm/tests/generated/2.0.csv @@ -1 +1,2 @@ -0.3.0-alpha.0,26722,1161,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"bulk.wast","passed":8,"failed":109},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":1},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":171,"failed":12},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_copy.wast","passed":3928,"failed":522},{"name":"memory_fill.wast","passed":64,"failed":36},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_init.wast","passed":177,"failed":63},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"ref_func.wast","passed":9,"failed":8},{"name":"ref_is_null.wast","passed":4,"failed":12},{"name":"ref_null.wast","passed":1,"failed":2},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"table_copy.wast","passed":1613,"failed":115},{"name":"table_fill.wast","passed":23,"failed":22},{"name":"table_get.wast","passed":10,"failed":6},{"name":"table_grow.wast","passed":21,"failed":29},{"name":"table_init.wast","passed":594,"failed":186},{"name":"table_set.wast","passed":19,"failed":7},{"name":"table_size.wast","passed":8,"failed":31},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0,26722,1161,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"bulk.wast","passed":8,"failed":109},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":98,"failed":1},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":171,"failed":12},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_copy.wast","passed":3928,"failed":522},{"name":"memory_fill.wast","passed":64,"failed":36},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_init.wast","passed":177,"failed":63},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"ref_func.wast","passed":9,"failed":8},{"name":"ref_is_null.wast","passed":4,"failed":12},{"name":"ref_null.wast","passed":1,"failed":2},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"table_copy.wast","passed":1613,"failed":115},{"name":"table_fill.wast","passed":23,"failed":22},{"name":"table_get.wast","passed":10,"failed":6},{"name":"table_grow.wast","passed":21,"failed":29},{"name":"table_init.wast","passed":594,"failed":186},{"name":"table_set.wast","passed":19,"failed":7},{"name":"table_size.wast","passed":8,"failed":31},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.4.0-alpha.0,26841,1042,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"bulk.wast","passed":8,"failed":109},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":99,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_copy.wast","passed":3928,"failed":522},{"name":"memory_fill.wast","passed":64,"failed":36},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_init.wast","passed":177,"failed":63},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"ref_func.wast","passed":9,"failed":8},{"name":"ref_is_null.wast","passed":4,"failed":12},{"name":"ref_null.wast","passed":1,"failed":2},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table-sub.wast","passed":2,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"table_copy.wast","passed":1613,"failed":115},{"name":"table_fill.wast","passed":23,"failed":22},{"name":"table_get.wast","passed":10,"failed":6},{"name":"table_grow.wast","passed":21,"failed":29},{"name":"table_init.wast","passed":700,"failed":80},{"name":"table_set.wast","passed":19,"failed":7},{"name":"table_size.wast","passed":8,"failed":31},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 7e16714..23c080d 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -2,4 +2,4 @@ 0.0.5,11135,9093,[{"name":"address.wast","passed":1,"failed":259},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":78,"failed":13},{"name":"binary.wast","passed":107,"failed":5},{"name":"block.wast","passed":170,"failed":53},{"name":"br.wast","passed":20,"failed":77},{"name":"br_if.wast","passed":29,"failed":89},{"name":"br_table.wast","passed":24,"failed":150},{"name":"call.wast","passed":18,"failed":73},{"name":"call_indirect.wast","passed":34,"failed":136},{"name":"comments.wast","passed":5,"failed":3},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":25,"failed":594},{"name":"custom.wast","passed":10,"failed":1},{"name":"data.wast","passed":22,"failed":39},{"name":"elem.wast","passed":27,"failed":72},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":90,"failed":6},{"name":"f32.wast","passed":1018,"failed":1496},{"name":"f32_bitwise.wast","passed":4,"failed":360},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":1018,"failed":1496},{"name":"f64_bitwise.wast","passed":4,"failed":360},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":1,"failed":7},{"name":"float_exprs.wast","passed":275,"failed":625},{"name":"float_literals.wast","passed":112,"failed":51},{"name":"float_memory.wast","passed":0,"failed":90},{"name":"float_misc.wast","passed":138,"failed":303},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":81,"failed":91},{"name":"func_ptrs.wast","passed":7,"failed":29},{"name":"global.wast","passed":50,"failed":60},{"name":"i32.wast","passed":85,"failed":375},{"name":"i64.wast","passed":31,"failed":385},{"name":"if.wast","passed":116,"failed":125},{"name":"imports.wast","passed":23,"failed":160},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":38,"failed":70},{"name":"int_literals.wast","passed":25,"failed":26},{"name":"labels.wast","passed":13,"failed":16},{"name":"left-to-right.wast","passed":0,"failed":96},{"name":"linking.wast","passed":5,"failed":127},{"name":"load.wast","passed":59,"failed":38},{"name":"local_get.wast","passed":18,"failed":18},{"name":"local_set.wast","passed":38,"failed":15},{"name":"local_tee.wast","passed":41,"failed":56},{"name":"loop.wast","passed":42,"failed":78},{"name":"memory.wast","passed":30,"failed":49},{"name":"memory_grow.wast","passed":11,"failed":85},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":1,"failed":181},{"name":"names.wast","passed":484,"failed":2},{"name":"nop.wast","passed":4,"failed":84},{"name":"return.wast","passed":20,"failed":64},{"name":"select.wast","passed":28,"failed":120},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":4,"failed":16},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":39,"failed":19},{"name":"traps.wast","passed":4,"failed":32},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":0,"failed":64},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":9,"failed":41},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20254,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":99,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0,20254,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":99,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] From 79463500a7ade3df7dc99454f5797beaf1d7eef9 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 25 Jan 2024 13:49:52 +0100 Subject: [PATCH 47/52] chore: refactor executor and improve documentation Signed-off-by: Henry Gressmann --- .github/workflows/test.yaml | 2 +- crates/parser/src/error.rs | 1 + crates/tinywasm/src/error.rs | 26 ++--- crates/tinywasm/src/func.rs | 4 +- crates/tinywasm/src/imports.rs | 109 +++++++++++------- crates/tinywasm/src/instance.rs | 8 +- crates/tinywasm/src/lib.rs | 40 ++++--- .../{executor => interpreter}/macros.rs | 0 .../runtime/{executor => interpreter}/mod.rs | 17 ++- .../{executor => interpreter}/traits.rs | 0 crates/tinywasm/src/runtime/mod.rs | 20 ++-- .../tinywasm/src/runtime/stack/call_stack.rs | 7 +- crates/tinywasm/src/store.rs | 10 +- crates/tinywasm/tests/generated/mvp.csv | 1 + 14 files changed, 140 insertions(+), 105 deletions(-) rename crates/tinywasm/src/runtime/{executor => interpreter}/macros.rs (100%) rename crates/tinywasm/src/runtime/{executor => interpreter}/mod.rs (98%) rename crates/tinywasm/src/runtime/{executor => interpreter}/traits.rs (100%) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 2631077..41dd979 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -38,7 +38,7 @@ jobs: submodules: true - name: Install nightly Rust toolchain - run: rustup update stable nightly + run: rustup update nightly - name: Build (nightly, no default features) run: cargo +nightly build --workspace --exclude wasm-testsuite --no-default-features diff --git a/crates/parser/src/error.rs b/crates/parser/src/error.rs index 714535a..35bad28 100644 --- a/crates/parser/src/error.rs +++ b/crates/parser/src/error.rs @@ -4,6 +4,7 @@ use alloc::string::{String, ToString}; use wasmparser::Encoding; #[derive(Debug)] +/// Errors that can occur when parsing a WebAssembly module pub enum ParseError { InvalidType, UnsupportedSection(String), diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index f9b41be..0344e82 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -3,24 +3,18 @@ use core::fmt::Display; use tinywasm_types::FuncType; #[cfg(feature = "parser")] -use tinywasm_parser::ParseError; +pub use tinywasm_parser::ParseError; -/// A tinywasm error +/// Errors that can occur for TinyWasm operations #[derive(Debug)] pub enum Error { - #[cfg(feature = "parser")] - /// A parsing error occurred - ParseError(ParseError), - #[cfg(feature = "std")] /// An I/O error occurred Io(crate::std::io::Error), - /// A WebAssembly feature is not supported - UnsupportedFeature(String), - - /// An unknown error occurred - Other(String), + #[cfg(feature = "parser")] + /// A parsing error occurred + ParseError(ParseError), /// A WebAssembly trap occurred Trap(Trap), @@ -28,6 +22,12 @@ pub enum Error { /// A linking error occurred Linker(LinkingError), + /// A WebAssembly feature is not supported + UnsupportedFeature(String), + + /// An unknown error occurred + Other(String), + /// A function did not return a value FuncDidNotReturn, @@ -48,7 +48,7 @@ pub enum Error { } #[derive(Debug)] -/// A linking error +/// Errors that can occur when linking a WebAssembly module pub enum LinkingError { /// An unknown import was encountered UnknownImport { @@ -210,5 +210,5 @@ impl From for Error { } } -/// A specialized [`Result`] type for tinywasm operations +/// A wrapper around [`core::result::Result`] for tinywasm operations pub type Result = crate::std::result::Result; diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index 19d1325..7a29e18 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -89,7 +89,7 @@ impl FuncHandle { #[derive(Debug)] /// A typed function handle -pub struct TypedFuncHandle { +pub struct FuncHandleTyped { /// The underlying function handle pub func: FuncHandle, pub(crate) marker: core::marker::PhantomData<(P, R)>, @@ -105,7 +105,7 @@ pub trait FromWasmValueTuple { Self: Sized; } -impl TypedFuncHandle { +impl FuncHandleTyped { /// Call a typed function pub fn call(&self, store: &mut Store, params: P) -> Result { // Convert params into Vec diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 804aa12..0720d02 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -90,56 +90,45 @@ impl Debug for HostFunction { /// An external value pub enum Extern { /// A global value - Global(ExternGlobal), + Global { + /// The type of the global value. + ty: GlobalType, + /// The actual value of the global, encapsulated in `WasmValue`. + val: WasmValue, + }, /// A table - Table(ExternTable), + Table { + /// Defines the type of the table, including its element type and limits. + ty: TableType, + /// The initial value of the table. + init: WasmValue, + }, /// A memory - Memory(ExternMemory), + Memory { + /// Defines the type of the memory, including its limits and the type of its pages. + ty: MemoryType, + }, /// A function Function(Function), } -/// A function -#[derive(Debug, Clone)] -pub struct ExternFunc(pub(crate) HostFunction); - -/// A global value -#[derive(Debug, Clone)] -pub struct ExternGlobal { - pub(crate) ty: GlobalType, - pub(crate) val: WasmValue, -} - -/// A table -#[derive(Debug, Clone)] -pub struct ExternTable { - pub(crate) ty: TableType, - pub(crate) val: WasmValue, -} - -/// A memory -#[derive(Debug, Clone)] -pub struct ExternMemory { - pub(crate) ty: MemoryType, -} - impl Extern { /// Create a new global import pub fn global(val: WasmValue, mutable: bool) -> Self { - Self::Global(ExternGlobal { ty: GlobalType { ty: val.val_type(), mutable }, val }) + Self::Global { ty: GlobalType { ty: val.val_type(), mutable }, val } } /// Create a new table import - pub fn table(ty: TableType, val: WasmValue) -> Self { - Self::Table(ExternTable { ty, val }) + pub fn table(ty: TableType, init: WasmValue) -> Self { + Self::Table { ty, init } } /// Create a new memory import pub fn memory(ty: MemoryType) -> Self { - Self::Memory(ExternMemory { ty }) + Self::Memory { ty } } /// Create a new function import @@ -174,10 +163,10 @@ impl Extern { pub(crate) fn kind(&self) -> ExternalKind { match self { - Self::Global(_) => ExternalKind::Global, - Self::Table(_) => ExternalKind::Table, - Self::Memory(_) => ExternalKind::Memory, - Self::Function(_) => ExternalKind::Func, + Self::Global { .. } => ExternalKind::Global, + Self::Table { .. } => ExternalKind::Table, + Self::Memory { .. } => ExternalKind::Memory, + Self::Function { .. } => ExternalKind::Func, } } } @@ -197,6 +186,38 @@ impl From<&Import> for ExternName { #[derive(Debug, Default)] /// Imports for a module instance +/// +/// This is used to link a module instance to its imports +/// +/// ## Example +/// ```rust +/// # fn main() -> tinywasm::Result<()> { +/// use tinywasm::{Imports, Extern}; +/// use tinywasm::types::{ValType, TableType, MemoryType, WasmValue}; +/// let mut imports = Imports::new(); +/// +/// // function args can be either a single +/// // value that implements `TryFrom` or a tuple of them +/// let print_i32 = Extern::typed_func(|_ctx: tinywasm::FuncContext<'_>, arg: i32| { +/// log::debug!("print_i32: {}", arg); +/// Ok(()) +/// }); +/// +/// let table_type = TableType::new(ValType::RefFunc, 10, Some(20)); +/// let table_init = WasmValue::default_for(ValType::RefFunc); +/// +/// imports +/// .define("my_module", "print_i32", print_i32)? +/// .define("my_module", "table", Extern::table(table_type, table_init))? +/// .define("my_module", "memory", Extern::memory(MemoryType::new_32(1, Some(2))))? +/// .define("my_module", "global_i32", Extern::global(WasmValue::I32(666), false))? +/// .link_module("my_other_module", 0)?; +/// # Ok(()) +/// # } +/// ``` +/// +/// Note that module instance addresses for [`Imports::link_module`] can be obtained from [`crate::ModuleInstance::id`]. +/// Now, the imports object can be passed to [`crate::ModuleInstance::instantiate`]. pub struct Imports { values: BTreeMap, modules: BTreeMap, @@ -334,17 +355,17 @@ impl Imports { match val { // A link to something that needs to be added to the store ResolvedExtern::Extern(ex) => match (ex, &import.kind) { - (Extern::Global(extern_global), ImportKind::Global(ty)) => { - Self::compare_types(import, &extern_global.ty, ty)?; - imports.globals.push(store.add_global(extern_global.ty, extern_global.val.into(), idx)?); + (Extern::Global { ty, val }, ImportKind::Global(import_ty)) => { + Self::compare_types(import, &ty, import_ty)?; + imports.globals.push(store.add_global(ty, val.into(), idx)?); } - (Extern::Table(extern_table), ImportKind::Table(ty)) => { - Self::compare_table_types(import, &extern_table.ty, ty)?; - imports.tables.push(store.add_table(extern_table.ty, idx)?); + (Extern::Table { ty, .. }, ImportKind::Table(import_ty)) => { + Self::compare_table_types(import, &ty, import_ty)?; + imports.tables.push(store.add_table(ty, idx)?); } - (Extern::Memory(extern_memory), ImportKind::Memory(ty)) => { - Self::compare_memory_types(import, &extern_memory.ty, ty, None)?; - imports.memories.push(store.add_mem(extern_memory.ty, idx)?); + (Extern::Memory { ty }, ImportKind::Memory(import_ty)) => { + Self::compare_memory_types(import, &ty, import_ty, None)?; + imports.memories.push(store.add_mem(ty, idx)?); } (Extern::Function(extern_func), ImportKind::Function(ty)) => { let import_func_type = module diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index d1fbd6f..75d1f87 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -6,10 +6,10 @@ use tinywasm_types::{ use crate::{ func::{FromWasmValueTuple, IntoWasmValueTuple}, - Error, FuncHandle, Imports, Module, Result, Store, TypedFuncHandle, + Error, FuncHandle, FuncHandleTyped, Imports, Module, Result, Store, }; -/// A WebAssembly Module Instance +/// An instanciated WebAssembly module /// /// Backed by an Arc, so cloning is cheap /// @@ -178,13 +178,13 @@ impl ModuleInstance { } /// Get a typed exported function by name - pub fn typed_func(&self, store: &Store, name: &str) -> Result> + pub fn typed_func(&self, store: &Store, name: &str) -> Result> where P: IntoWasmValueTuple, R: FromWasmValueTuple, { let func = self.exported_func_by_name(store, name)?; - Ok(TypedFuncHandle { func, marker: core::marker::PhantomData }) + Ok(FuncHandleTyped { func, marker: core::marker::PhantomData }) } /// Get the start function of the module diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs index 64d34df..1b63b99 100644 --- a/crates/tinywasm/src/lib.rs +++ b/crates/tinywasm/src/lib.rs @@ -14,12 +14,23 @@ //! to be useful for embedded systems and other environments where a full-featured //! runtime is not required. //! -//! ## Getting Started +//! ## Features +//! - `std` (default): Enables the use of `std` and `std::io` for parsing from files and streams. +//! - `logging` (default): Enables logging via the `log` crate. +//! - `parser` (default): Enables the `tinywasm_parser` crate for parsing WebAssembly modules. +//! +//! ## No-std support +//! TinyWasm supports `no_std` environments by disabling the `std` feature and registering +//! a custom allocator. This removes support for parsing from files and streams, +//! but otherwise the API is the same. +//! Additionally, to have proper error types, you currently need a `nightly` compiler to have the error trait in core. //! +//! ## Getting Started //! The easiest way to get started is to use the [`Module::parse_bytes`] function to load a //! WebAssembly module from bytes. This will parse the module and validate it, returning //! a [`Module`] that can be used to instantiate the module. //! +//! //! ```rust //! use tinywasm::{Store, Module}; //! @@ -39,25 +50,21 @@ //! //! // Get a typed handle to the exported "add" function //! // Alternatively, you can use `instance.get_func` to get an untyped handle -//! // that takes and returns WasmValue types -//! let func = instance.typed_func::<(i32, i32), (i32,)>(&mut store, "add")?; +//! // that takes and returns [`WasmValue`]s +//! let func = instance.typed_func::<(i32, i32), i32>(&mut store, "add")?; //! let res = func.call(&mut store, (1, 2))?; //! -//! assert_eq!(res, (3,)); +//! assert_eq!(res, 3); //! # Ok::<(), tinywasm::Error>(()) //! ``` //! -//! ## Features -//! - `std` (default): Enables the use of `std` and `std::io` for parsing from files and streams. -//! - `logging` (default): Enables logging via the `log` crate. -//! - `parser` (default): Enables the `tinywasm_parser` crate for parsing WebAssembly modules. +//! ## Custom Imports //! -//! ## No-std support -//! TinyWasm supports `no_std` environments by disabling the `std` feature and registering -//! a custom allocator. This removes support for parsing from files and streams, -//! but otherwise the API is the same. +//! To provide custom imports to a module, you can use the [`Imports`] struct. +//! This struct allows you to register custom functions, globals, memories, tables, +//! and other modules to be linked into the module when it is instantiated. //! -//! Additionally, if you want proper error types, you must use a `nightly` compiler to have the error trait in core. +//! See the [`Imports`] documentation for more information. mod std; extern crate alloc; @@ -87,13 +94,14 @@ mod instance; pub use instance::ModuleInstance; mod func; -pub use func::{FuncHandle, TypedFuncHandle}; +pub use func::{FuncHandle, FuncHandleTyped}; mod imports; pub use imports::*; -mod runtime; -pub use runtime::*; +/// Runtime for executing WebAssembly modules. +pub mod runtime; +pub use runtime::InterpreterRuntime; #[cfg(feature = "parser")] /// Re-export of [`tinywasm_parser`]. Requires `parser` feature. diff --git a/crates/tinywasm/src/runtime/executor/macros.rs b/crates/tinywasm/src/runtime/interpreter/macros.rs similarity index 100% rename from crates/tinywasm/src/runtime/executor/macros.rs rename to crates/tinywasm/src/runtime/interpreter/macros.rs diff --git a/crates/tinywasm/src/runtime/executor/mod.rs b/crates/tinywasm/src/runtime/interpreter/mod.rs similarity index 98% rename from crates/tinywasm/src/runtime/executor/mod.rs rename to crates/tinywasm/src/runtime/interpreter/mod.rs index d0f011f..48ce21d 100644 --- a/crates/tinywasm/src/runtime/executor/mod.rs +++ b/crates/tinywasm/src/runtime/interpreter/mod.rs @@ -1,10 +1,10 @@ use core::ops::{BitAnd, BitOr, BitXor, Neg}; -use super::{DefaultRuntime, Stack}; +use super::{InterpreterRuntime, Stack}; use crate::{ log::debug, - runtime::{BlockType, LabelFrame}, - CallFrame, Error, FuncContext, LabelArgs, ModuleInstance, Result, Store, Trap, + runtime::{BlockType, CallFrame, LabelArgs, LabelFrame}, + Error, FuncContext, ModuleInstance, Result, Store, Trap, }; use alloc::{string::ToString, vec::Vec}; use tinywasm_types::{ElementKind, Instruction, ValType}; @@ -14,7 +14,7 @@ mod traits; use macros::*; use traits::*; -impl DefaultRuntime { +impl InterpreterRuntime { pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack) -> Result<()> { // The current call frame, gets updated inside of exec_one let mut cf = stack.call_stack.pop()?; @@ -246,7 +246,7 @@ fn exec_one( instr_ptr: cf.instr_ptr + *else_offset, end_instr_ptr: cf.instr_ptr + *end_offset, stack_ptr: stack.values.len(), // - params, - args: crate::LabelArgs::new(*args, module)?, + args: LabelArgs::new(*args, module)?, ty: BlockType::Else, }, &mut stack.values, @@ -302,11 +302,8 @@ fn exec_one( } let idx = stack.values.pop_t::()? as usize; - if let Some(label) = instr.get(idx) { - break_to!(cf, stack, label); - } else { - break_to!(cf, stack, default); - } + let to = instr.get(idx).unwrap_or(default); + break_to!(cf, stack, to); } Br(v) => break_to!(cf, stack, v), diff --git a/crates/tinywasm/src/runtime/executor/traits.rs b/crates/tinywasm/src/runtime/interpreter/traits.rs similarity index 100% rename from crates/tinywasm/src/runtime/executor/traits.rs rename to crates/tinywasm/src/runtime/interpreter/traits.rs diff --git a/crates/tinywasm/src/runtime/mod.rs b/crates/tinywasm/src/runtime/mod.rs index 610810f..3b9a57c 100644 --- a/crates/tinywasm/src/runtime/mod.rs +++ b/crates/tinywasm/src/runtime/mod.rs @@ -1,19 +1,23 @@ -mod executor; +mod interpreter; mod stack; mod value; pub use stack::*; pub(crate) use value::RawWasmValue; +use crate::Result; + #[allow(rustdoc::private_intra_doc_links)] -/// A WebAssembly Runtime. -/// -/// Generic over `CheckTypes` to enable type checking at runtime. -/// This is useful for debugging, but should be disabled if you know -/// that the module is valid. +/// A WebAssembly runtime. /// /// See +pub trait Runtime { + /// Execute all call-frames on the stack until the stack is empty. + fn exec(&self, store: &mut crate::Store, stack: &mut crate::runtime::Stack) -> Result<()>; +} + +/// The main TinyWasm runtime. /// -/// Execution is implemented in the [`crate::runtime::executor`] module +/// This is the default runtime used by TinyWasm. #[derive(Debug, Default)] -pub struct DefaultRuntime {} +pub struct InterpreterRuntime {} diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index 1bcd474..098b918 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -1,8 +1,11 @@ -use crate::{runtime::RawWasmValue, BlockType, Error, FunctionInstance, LabelFrame, Result, Trap}; +use crate::{ + runtime::{BlockType, RawWasmValue}, + Error, FunctionInstance, Result, Trap, +}; use alloc::{boxed::Box, rc::Rc, vec::Vec}; use tinywasm_types::{ValType, WasmValue}; -use super::blocks::Labels; +use super::{blocks::Labels, LabelFrame}; // minimum call stack size const CALL_STACK_SIZE: usize = 128; diff --git a/crates/tinywasm/src/store.rs b/crates/tinywasm/src/store.rs index aabbf71..4d3e326 100644 --- a/crates/tinywasm/src/store.rs +++ b/crates/tinywasm/src/store.rs @@ -7,8 +7,8 @@ use alloc::{boxed::Box, format, rc::Rc, string::ToString, vec, vec::Vec}; use tinywasm_types::*; use crate::{ - runtime::{self, DefaultRuntime}, - Error, Function, ModuleInstance, RawWasmValue, Result, Trap, + runtime::{self, InterpreterRuntime, RawWasmValue}, + Error, Function, ModuleInstance, Result, Trap, }; // global store id counter @@ -51,9 +51,9 @@ impl Store { } /// Create a new store with the given runtime - pub(crate) fn runtime(&self) -> runtime::DefaultRuntime { + pub(crate) fn runtime(&self) -> runtime::InterpreterRuntime { match self.runtime { - Runtime::Default => DefaultRuntime::default(), + Runtime::Default => InterpreterRuntime::default(), } } } @@ -441,7 +441,7 @@ impl Store { /// A WebAssembly Function Instance /// /// See -pub struct FunctionInstance { +pub(crate) struct FunctionInstance { pub(crate) func: Function, pub(crate) _type_idx: TypeAddr, pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 23c080d..03241b3 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -3,3 +3,4 @@ 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.3.0,20254,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":99,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] +0.3.0-alpha.0,20254,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":99,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] From b9a4e8788f374dac94e4f3f5b062dbe2a1d2a10c Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Thu, 25 Jan 2024 16:15:36 +0100 Subject: [PATCH 48/52] docs: update readme Signed-off-by: Henry Gressmann --- README.md | 56 ++++++++++++++----- crates/tinywasm/src/lib.rs | 4 +- crates/tinywasm/tests/generated/mvp.csv | 1 - .../tinywasm/tests/generated/progress-mvp.svg | 8 +-- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 00b828e..ac755c7 100644 --- a/README.md +++ b/README.md @@ -10,20 +10,43 @@ [![docs.rs](https://img.shields.io/docsrs/tinywasm?logo=rust)](https://docs.rs/tinywasm) [![Crates.io](https://img.shields.io/crates/v/tinywasm.svg?logo=rust)](https://crates.io/crates/tinywasm) [![Crates.io](https://img.shields.io/crates/l/tinywasm.svg)](./LICENSE-APACHE) -# 🚧 Status +# Status -> [!WARNING] -> This project is still in development and is not ready for use. +TinyWasm, starting from upcoming version `0.3.0`, passes all the WebAssembly 1.0 tests in the [WebAssembly Test Suite](https://github.com/WebAssembly/testsuite). The 2.0 tests are in progress (notably `simd` and `bulk-memory-operations` are not implemented yet). -I'm currently working on supporting the WebAssembly MVP (1.0) specification. You can see the current status in the graph below. The goal is to support all the features of the MVP specification and then move on to the next version. +Some APIs to interact with the runtime are not yet exposed, and the existing ones are subject to change, but the core functionality is mostly complete. +Results of the tests can be found [here](https://github.com/explodingcamera/tinywasm/tree/main/crates/tinywasm/tests/generated). -

- - - -

+TinyWasm is not designed for performance, but rather for size and portability. However, it is still reasonably fast. +There are a couple of low-hanging fruits on the performance side, but they are not a priority at the moment. -## Features +## Supported Proposals + +- [**Mutable Globals**](https://github.com/WebAssembly/mutable-global/blob/master/proposals/mutable-global/Overview.md) - **Fully implemented** +- [**Multi-value**](https://github.com/WebAssembly/spec/blob/master/proposals/multi-value/Overview.md) - **Fully implemented** +- [**Sign-extension operators**](https://github.com/WebAssembly/spec/blob/master/proposals/sign-extension-ops/Overview.md) - **Fully implemented** +- [**Reference Types**](https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md) - **_Partially implemented_** +- [**Multiple Memories**](https://github.com/WebAssembly/multi-memory/blob/master/proposals/multi-memory/Overview.md) - **_Partially implemented_** (not tested yet) +- [**Memory64**](https://github.com/WebAssembly/memory64/blob/master/proposals/memory64/Overview.md) - **_Partially implemented_** (only 32-bit addressing is supported at the moment, but larger memories can be created) + +## Usage + +TinyWasm can be used through the `tinywasm-cli` CLI tool or as a library in your Rust project. Documentation can be found [here](https://docs.rs/tinywasm). + +### CLI + +```sh +$ cargo install tinywasm-cli +$ tinywasm-cli --help +``` + +### Library + +```sh +$ cargo add tinywasm +``` + +## Feature Flags - **`std`**\ Enables the use of `std` and `std::io` for parsing from files and streams. This is enabled by default. @@ -32,16 +55,21 @@ I'm currently working on supporting the WebAssembly MVP (1.0) specification. You - **`parser`**\ Enables the `tinywasm-parser` crate. This is enabled by default. -# 🎯 Goals +With all these features disabled, TinyWasm does not depend on any external crates and can be used in `no_std` environments. + + + +## Performance + +> Benchmarks are coming soon. # 📄 License @@ -49,4 +77,4 @@ Licensed under either of [Apache License, Version 2.0](./LICENSE-APACHE) or [MIT Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in TinyWasm by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. -**Note:** The GitHub repository contains a Submodule (`crates/tinywasm-parser/data`) which is licensed only under the [Apache License, Version 2.0](https://github.com/WebAssembly/spec/blob/main/test/LICENSE). This is because the data is generated from the [WebAssembly Specification](https://github.com/WebAssembly/spec/tree/main/test) and is only used for testing purposes and is not included in the final binary. +**Note:** The GitHub repository contains a Submodule (`crates/tinywasm-parser/data`) which is licensed only under the [Apache License, Version 2.0](https://github.com/WebAssembly/spec/blob/main/test/LICENSE). This data is generated from the [WebAssembly Specification](https://github.com/WebAssembly/spec/tree/main/test) and is only used for testing purposes and not included in the final binary. diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs index 1b63b99..5388c05 100644 --- a/crates/tinywasm/src/lib.rs +++ b/crates/tinywasm/src/lib.rs @@ -58,9 +58,9 @@ //! # Ok::<(), tinywasm::Error>(()) //! ``` //! -//! ## Custom Imports +//! ## Imports //! -//! To provide custom imports to a module, you can use the [`Imports`] struct. +//! To provide imports to a module, you can use the [`Imports`] struct. //! This struct allows you to register custom functions, globals, memories, tables, //! and other modules to be linked into the module when it is instantiated. //! diff --git a/crates/tinywasm/tests/generated/mvp.csv b/crates/tinywasm/tests/generated/mvp.csv index 03241b3..23c080d 100644 --- a/crates/tinywasm/tests/generated/mvp.csv +++ b/crates/tinywasm/tests/generated/mvp.csv @@ -3,4 +3,3 @@ 0.1.0,17630,2598,[{"name":"address.wast","passed":5,"failed":255},{"name":"align.wast","passed":108,"failed":48},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":110,"failed":2},{"name":"block.wast","passed":193,"failed":30},{"name":"br.wast","passed":84,"failed":13},{"name":"br_if.wast","passed":90,"failed":28},{"name":"br_table.wast","passed":25,"failed":149},{"name":"call.wast","passed":29,"failed":62},{"name":"call_indirect.wast","passed":36,"failed":134},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":371,"failed":248},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":50,"failed":49},{"name":"endianness.wast","passed":1,"failed":68},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":2,"failed":6},{"name":"float_exprs.wast","passed":761,"failed":139},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":6,"failed":84},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":1,"failed":4},{"name":"func.wast","passed":124,"failed":48},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":51,"failed":59},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":120,"failed":121},{"name":"imports.wast","passed":74,"failed":109},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":14,"failed":15},{"name":"left-to-right.wast","passed":1,"failed":95},{"name":"linking.wast","passed":21,"failed":111},{"name":"load.wast","passed":60,"failed":37},{"name":"local_get.wast","passed":32,"failed":4},{"name":"local_set.wast","passed":50,"failed":3},{"name":"local_tee.wast","passed":68,"failed":29},{"name":"loop.wast","passed":93,"failed":27},{"name":"memory.wast","passed":34,"failed":45},{"name":"memory_grow.wast","passed":12,"failed":84},{"name":"memory_redundancy.wast","passed":1,"failed":7},{"name":"memory_size.wast","passed":6,"failed":36},{"name":"memory_trap.wast","passed":2,"failed":180},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":46,"failed":42},{"name":"return.wast","passed":73,"failed":11},{"name":"select.wast","passed":86,"failed":62},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":2,"failed":5},{"name":"start.wast","passed":9,"failed":11},{"name":"store.wast","passed":59,"failed":9},{"name":"switch.wast","passed":2,"failed":26},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":22,"failed":14},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":50,"failed":14},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":35,"failed":15},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.2.0,19344,884,[{"name":"address.wast","passed":181,"failed":79},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":220,"failed":3},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":171,"failed":3},{"name":"call.wast","passed":73,"failed":18},{"name":"call_indirect.wast","passed":50,"failed":120},{"name":"comments.wast","passed":7,"failed":1},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":439,"failed":180},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":47,"failed":14},{"name":"elem.wast","passed":56,"failed":43},{"name":"endianness.wast","passed":29,"failed":40},{"name":"exports.wast","passed":92,"failed":4},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":6,"failed":2},{"name":"float_exprs.wast","passed":890,"failed":10},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":78,"failed":12},{"name":"float_misc.wast","passed":437,"failed":4},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":168,"failed":4},{"name":"func_ptrs.wast","passed":10,"failed":26},{"name":"global.wast","passed":103,"failed":7},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":231,"failed":10},{"name":"imports.wast","passed":80,"failed":103},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":26,"failed":3},{"name":"left-to-right.wast","passed":92,"failed":4},{"name":"linking.wast","passed":29,"failed":103},{"name":"load.wast","passed":93,"failed":4},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":93,"failed":4},{"name":"loop.wast","passed":116,"failed":4},{"name":"memory.wast","passed":78,"failed":1},{"name":"memory_grow.wast","passed":91,"failed":5},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":35,"failed":7},{"name":"memory_trap.wast","passed":180,"failed":2},{"name":"names.wast","passed":485,"failed":1},{"name":"nop.wast","passed":78,"failed":10},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":114,"failed":34},{"name":"skip-stack-guard-page.wast","passed":1,"failed":10},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":11,"failed":9},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] 0.3.0,20254,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":99,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] -0.3.0-alpha.0,20254,0,[{"name":"address.wast","passed":260,"failed":0},{"name":"align.wast","passed":156,"failed":0},{"name":"binary-leb128.wast","passed":91,"failed":0},{"name":"binary.wast","passed":112,"failed":0},{"name":"block.wast","passed":223,"failed":0},{"name":"br.wast","passed":97,"failed":0},{"name":"br_if.wast","passed":118,"failed":0},{"name":"br_table.wast","passed":174,"failed":0},{"name":"call.wast","passed":91,"failed":0},{"name":"call_indirect.wast","passed":170,"failed":0},{"name":"comments.wast","passed":8,"failed":0},{"name":"const.wast","passed":778,"failed":0},{"name":"conversions.wast","passed":619,"failed":0},{"name":"custom.wast","passed":11,"failed":0},{"name":"data.wast","passed":61,"failed":0},{"name":"elem.wast","passed":99,"failed":0},{"name":"endianness.wast","passed":69,"failed":0},{"name":"exports.wast","passed":96,"failed":0},{"name":"f32.wast","passed":2514,"failed":0},{"name":"f32_bitwise.wast","passed":364,"failed":0},{"name":"f32_cmp.wast","passed":2407,"failed":0},{"name":"f64.wast","passed":2514,"failed":0},{"name":"f64_bitwise.wast","passed":364,"failed":0},{"name":"f64_cmp.wast","passed":2407,"failed":0},{"name":"fac.wast","passed":8,"failed":0},{"name":"float_exprs.wast","passed":900,"failed":0},{"name":"float_literals.wast","passed":163,"failed":0},{"name":"float_memory.wast","passed":90,"failed":0},{"name":"float_misc.wast","passed":441,"failed":0},{"name":"forward.wast","passed":5,"failed":0},{"name":"func.wast","passed":172,"failed":0},{"name":"func_ptrs.wast","passed":36,"failed":0},{"name":"global.wast","passed":110,"failed":0},{"name":"i32.wast","passed":460,"failed":0},{"name":"i64.wast","passed":416,"failed":0},{"name":"if.wast","passed":241,"failed":0},{"name":"imports.wast","passed":183,"failed":0},{"name":"inline-module.wast","passed":1,"failed":0},{"name":"int_exprs.wast","passed":108,"failed":0},{"name":"int_literals.wast","passed":51,"failed":0},{"name":"labels.wast","passed":29,"failed":0},{"name":"left-to-right.wast","passed":96,"failed":0},{"name":"linking.wast","passed":132,"failed":0},{"name":"load.wast","passed":97,"failed":0},{"name":"local_get.wast","passed":36,"failed":0},{"name":"local_set.wast","passed":53,"failed":0},{"name":"local_tee.wast","passed":97,"failed":0},{"name":"loop.wast","passed":120,"failed":0},{"name":"memory.wast","passed":79,"failed":0},{"name":"memory_grow.wast","passed":96,"failed":0},{"name":"memory_redundancy.wast","passed":8,"failed":0},{"name":"memory_size.wast","passed":42,"failed":0},{"name":"memory_trap.wast","passed":182,"failed":0},{"name":"names.wast","passed":486,"failed":0},{"name":"nop.wast","passed":88,"failed":0},{"name":"return.wast","passed":84,"failed":0},{"name":"select.wast","passed":148,"failed":0},{"name":"skip-stack-guard-page.wast","passed":11,"failed":0},{"name":"stack.wast","passed":7,"failed":0},{"name":"start.wast","passed":20,"failed":0},{"name":"store.wast","passed":68,"failed":0},{"name":"switch.wast","passed":28,"failed":0},{"name":"table.wast","passed":19,"failed":0},{"name":"token.wast","passed":58,"failed":0},{"name":"traps.wast","passed":36,"failed":0},{"name":"type.wast","passed":3,"failed":0},{"name":"unreachable.wast","passed":64,"failed":0},{"name":"unreached-invalid.wast","passed":118,"failed":0},{"name":"unreached-valid.wast","passed":7,"failed":0},{"name":"unwind.wast","passed":50,"failed":0},{"name":"utf8-custom-section-id.wast","passed":176,"failed":0},{"name":"utf8-import-field.wast","passed":176,"failed":0},{"name":"utf8-import-module.wast","passed":176,"failed":0},{"name":"utf8-invalid-encoding.wast","passed":176,"failed":0}] diff --git a/crates/tinywasm/tests/generated/progress-mvp.svg b/crates/tinywasm/tests/generated/progress-mvp.svg index e168cb9..c1200f5 100644 --- a/crates/tinywasm/tests/generated/progress-mvp.svg +++ b/crates/tinywasm/tests/generated/progress-mvp.svg @@ -53,12 +53,12 @@ v0.2.0 (19344) -v0.3.0-alpha.0 (20253) +v0.3.0 (20254) - - + - + + From 461126ce309f99e4ad2a6ddcbc175ea01c5e8fee Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Fri, 26 Jan 2024 01:26:09 +0100 Subject: [PATCH 49/52] feat: full no_std support Signed-off-by: Henry Gressmann --- .github/workflows/test.yaml | 4 +- Cargo.lock | 101 ++++++++++++++++++ Cargo.toml | 10 +- README.md | 2 +- crates/parser/src/conversion.rs | 6 +- crates/parser/src/lib.rs | 2 + crates/parser/src/module.rs | 4 +- crates/tinywasm/Cargo.toml | 1 + crates/tinywasm/src/func.rs | 6 +- crates/tinywasm/src/imports.rs | 2 +- crates/tinywasm/src/instance.rs | 5 +- crates/tinywasm/src/lib.rs | 6 ++ .../tinywasm/src/runtime/interpreter/mod.rs | 12 ++- .../src/runtime/interpreter/no_std_floats.rs | 77 +++++++++++++ .../src/runtime/interpreter/traits.rs | 3 + .../tinywasm/src/runtime/stack/call_stack.rs | 1 + .../tinywasm/src/runtime/stack/value_stack.rs | 1 + crates/tinywasm/src/store.rs | 8 +- crates/types/src/lib.rs | 19 ++-- examples/rust/Cargo.toml | 23 ++++ examples/rust/README.md | 1 + examples/rust/src/hello.rs | 18 ++++ examples/rust/src/tinywasm.rs | 41 +++++++ examples/wasm-rust.rs | 41 +++++++ 24 files changed, 363 insertions(+), 31 deletions(-) create mode 100644 crates/tinywasm/src/runtime/interpreter/no_std_floats.rs create mode 100644 examples/rust/Cargo.toml create mode 100644 examples/rust/README.md create mode 100644 examples/rust/src/hello.rs create mode 100644 examples/rust/src/tinywasm.rs create mode 100644 examples/wasm-rust.rs diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 41dd979..92d56f4 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -41,10 +41,10 @@ jobs: run: rustup update nightly - name: Build (nightly, no default features) - run: cargo +nightly build --workspace --exclude wasm-testsuite --no-default-features + run: cargo +nightly build --workspace --exclude wasm-testsuite --exclude rust-wasm-examples --no-default-features - name: Run tests (nightly, no default features) - run: cargo +nightly test --workspace --exclude wasm-testsuite --no-default-features + run: cargo +nightly test --workspace --exclude wasm-testsuite --exclude rust-wasm-examples --no-default-features - name: Run MVP testsuite (nightly) run: cargo +nightly test-mvp diff --git a/Cargo.lock b/Cargo.lock index e13a9f1..84cd8cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -229,10 +229,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" dependencies = [ "backtrace", + "color-spantrace", "eyre", "indenter", "once_cell", "owo-colors 3.5.0", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors 3.5.0", + "tracing-core", + "tracing-error", ] [[package]] @@ -684,6 +698,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "libredox" version = "0.0.1" @@ -778,6 +798,12 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + [[package]] name = "pkg-config" version = "0.3.29" @@ -1116,6 +1142,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -1185,6 +1220,16 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1205,6 +1250,7 @@ name = "tinywasm" version = "0.3.0-alpha.0" dependencies = [ "eyre", + "libm", "log", "owo-colors 4.0.0", "plotters", @@ -1238,6 +1284,14 @@ dependencies = [ "wasmparser-nostd", ] +[[package]] +name = "tinywasm-root" +version = "0.0.0" +dependencies = [ + "color-eyre", + "tinywasm", +] + [[package]] name = "tinywasm-types" version = "0.3.0-alpha.0" @@ -1246,6 +1300,47 @@ dependencies = [ "rkyv", ] +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + [[package]] name = "ttf-parser" version = "0.17.1" @@ -1276,6 +1371,12 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 0d5f97b..2be4dcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,5 @@ [workspace] members=["crates/*"] -default-members=["crates/cli"] resolver="2" [workspace.package] @@ -9,3 +8,12 @@ edition="2021" license="MIT OR Apache-2.0" authors=["Henry Gressmann "] repository="https://github.com/explodingcamera/tinywasm" + +[package] +name="tinywasm-root" +publish=false +edition="2021" + +[dev-dependencies] +color-eyre="0.6" +tinywasm={path="crates/tinywasm"} diff --git a/README.md b/README.md index ac755c7..3197cf1 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ $ cargo add tinywasm - **`parser`**\ Enables the `tinywasm-parser` crate. This is enabled by default. -With all these features disabled, TinyWasm does not depend on any external crates and can be used in `no_std` environments. +With all these features disabled, TinyWasm only depends on `core`, `alloc` and `libm` and can be used in `no_std` environments. +Since `libm` is not as performant as the compiler's built-in math intrinsics, it is recommended to use the `std` feature if possible (at least [for now](https://github.com/rust-lang/rfcs/issues/2505)). ## Performance diff --git a/crates/tinywasm/src/error.rs b/crates/tinywasm/src/error.rs index 0344e82..4f68eaa 100644 --- a/crates/tinywasm/src/error.rs +++ b/crates/tinywasm/src/error.rs @@ -186,8 +186,8 @@ impl Display for Error { #[cfg(feature = "std")] Self::Io(err) => write!(f, "I/O error: {}", err), - Self::Trap(trap) => write!(f, "trap: {}", trap.message()), - Self::Linker(err) => write!(f, "linking error: {}", err.message()), + Self::Trap(trap) => write!(f, "trap: {}", trap), + Self::Linker(err) => write!(f, "linking error: {}", err), Self::CallStackEmpty => write!(f, "call stack empty"), Self::InvalidLabelType => write!(f, "invalid label type"), Self::Other(message) => write!(f, "unknown error: {}", message), @@ -200,6 +200,42 @@ impl Display for Error { } } +impl Display for LinkingError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::UnknownImport { module, name } => write!(f, "unknown import: {}.{}", module, name), + Self::IncompatibleImportType { module, name } => { + write!(f, "incompatible import type: {}.{}", module, name) + } + } + } +} + +impl Display for Trap { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Unreachable => write!(f, "unreachable"), + Self::MemoryOutOfBounds { offset, len, max } => { + write!(f, "out of bounds memory access: offset={}, len={}, max={}", offset, len, max) + } + Self::TableOutOfBounds { offset, len, max } => { + write!(f, "out of bounds table access: offset={}, len={}, max={}", offset, len, max) + } + Self::DivisionByZero => write!(f, "integer divide by zero"), + Self::InvalidConversionToInt => write!(f, "invalid conversion to integer"), + Self::IntegerOverflow => write!(f, "integer overflow"), + Self::CallStackOverflow => write!(f, "call stack exhausted"), + Self::UndefinedElement { index } => write!(f, "undefined element: index={}", index), + Self::UninitializedElement { index } => { + write!(f, "uninitialized element: index={}", index) + } + Self::IndirectCallTypeMismatch { expected, actual } => { + write!(f, "indirect call type mismatch: expected={:?}, actual={:?}", expected, actual) + } + } + } +} + #[cfg(any(feature = "std", all(not(feature = "std"), nightly)))] impl crate::std::error::Error for Error {} diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..ce47073 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,22 @@ +# Examples + +## WasmRust + +These are examples using WebAssembly generated from Rust code. +To run these, you first need to build the Rust code into WebAssembly, since the wasm files are not included in the repository to keep it small. +This requires the `wasm32-unknown-unknown` target and `wasm-opt` to be installed (available via Binaryen). + +```bash +$ ./examples/rust/build.sh +``` + +Then you can run the examples: + +```bash +$ cargo run --example wasm-rust +``` + +Where `` is one of the following: + +- `hello`: A simple example that prints a number to the console. +- `tinywasm`: Runs `hello` using TinyWasm - inside of TinyWasm itself! diff --git a/examples/rust/Cargo.toml b/examples/rust/Cargo.toml index 91b6aed..9ff80dc 100644 --- a/examples/rust/Cargo.toml +++ b/examples/rust/Cargo.toml @@ -7,8 +7,7 @@ forced-target="wasm32-unknown-unknown" edition="2021" [dependencies] -tinywasm={path="../../crates/tinywasm", default-features=false, features=["parser"]} -embedded-alloc={version="0.5"} +tinywasm={path="../../crates/tinywasm", features=["parser", "std"]} [[bin]] name="hello" @@ -17,7 +16,3 @@ path="src/hello.rs" [[bin]] name="tinywasm" path="src/tinywasm.rs" - -[profile.release] -opt-level="z" -panic="abort" diff --git a/examples/rust/build.sh b/examples/rust/build.sh new file mode 100755 index 0000000..2c8069a --- /dev/null +++ b/examples/rust/build.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +cd "$(dirname "$0")" + +bins=("hello" "tinywasm") +exclude_wat=("tinywasm") +out_dir="../../target/wasm32-unknown-unknown/wasm" +dest_dir="out" + +for bin in "${bins[@]}"; do + cargo build --target wasm32-unknown-unknown --package rust-wasm-examples --profile=wasm --bin "$bin" + + cp "$out_dir/$bin.wasm" "$dest_dir/" + wasm-opt "$dest_dir/$bin.wasm" -o "$dest_dir/$bin.wasm" -O --intrinsic-lowering -O + + if [[ ! " ${exclude_wat[@]} " =~ " $bin " ]]; then + wasm2wat "$dest_dir/$bin.wasm" -o "$dest_dir/$bin.wat" + fi +done diff --git a/examples/rust/src/tinywasm.rs b/examples/rust/src/tinywasm.rs index 4edde66..52af7b9 100644 --- a/examples/rust/src/tinywasm.rs +++ b/examples/rust/src/tinywasm.rs @@ -1,41 +1,32 @@ -#![no_std] #![no_main] +use tinywasm::{Extern, FuncContext}; -use embedded_alloc::Heap; -// use tinywasm::{Extern, FuncContext}; - -#[cfg(not(test))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - core::arch::wasm32::unreachable() +#[link(wasm_import_module = "env")] +extern "C" { + fn printi32(x: i32); } -#[global_allocator] -static HEAP: Heap = Heap::empty(); - #[no_mangle] -pub unsafe extern "C" fn _start() { - // Initialize the allocator BEFORE you use it - { - use core::mem::MaybeUninit; - const HEAP_SIZE: usize = 1024; - static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; - unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) } - } - - // now the allocator is ready types like Box, Vec can be used. +pub extern "C" fn hello() { let _ = run(); } fn run() -> tinywasm::Result<()> { - // let module = tinywasm::Module::parse_bytes(include_bytes!("../out/hello.wasm"))?; - // let mut store = tinywasm::Store::default(); - - // let mut imports = tinywasm::Imports::new(); - // imports.define("env", "printi32", Extern::typed_func(|_: FuncContext<'_>, _: i32| Ok(())))?; - - // let instance = module.instantiate(&mut store, Some(imports))?; - // let add_and_print = instance.typed_func::<(i32, i32), ()>(&mut store, "add_and_print")?; - // add_and_print.call(&mut store, (1, 2))?; + let module = tinywasm::Module::parse_bytes(include_bytes!("../../wasm/hello.wasm"))?; + let mut store = tinywasm::Store::default(); + let mut imports = tinywasm::Imports::new(); + + imports.define( + "env", + "printi32", + Extern::typed_func(|_: FuncContext<'_>, v: i32| { + unsafe { printi32(v) } + Ok(()) + }), + )?; + let instance = module.instantiate(&mut store, Some(imports))?; + + let add_and_print = instance.typed_func::<(i32, i32), ()>(&mut store, "add_and_print")?; + add_and_print.call(&mut store, (1, 2))?; Ok(()) } diff --git a/examples/wasm-rust.rs b/examples/wasm-rust.rs index 21d3eb8..3b8877e 100644 --- a/examples/wasm-rust.rs +++ b/examples/wasm-rust.rs @@ -7,35 +7,59 @@ fn main() -> Result<()> { println!("Usage: cargo run --example wasm-rust "); println!("Available examples:"); println!(" hello"); + println!(" tinywasm"); return Ok(()); } match args[1].as_str() { "hello" => hello()?, + "tinywasm" => tinywasm()?, _ => {} } Ok(()) } +fn tinywasm() -> Result<()> { + const TINYWASM: &[u8] = include_bytes!("./rust/out/tinywasm.wasm"); + let module = Module::parse_bytes(&TINYWASM)?; + let mut store = Store::default(); + + let mut imports = Imports::new(); + imports.define( + "env", + "printi32", + Extern::typed_func(|_: FuncContext<'_>, x: i32| { + println!("{}", x); + Ok(()) + }), + )?; + let instance = module.instantiate(&mut store, Some(imports))?; + + let hello = instance.typed_func::<(), ()>(&mut store, "hello")?; + hello.call(&mut store, ())?; + + Ok(()) +} + fn hello() -> Result<()> { - // const HELLO_WASM: &[u8] = include_bytes!("./rust/out/hello.wasm"); - // let module = Module::parse_bytes(&HELLO_WASM)?; - // let mut store = Store::default(); - - // let mut imports = Imports::new(); - // imports.define( - // "env", - // "printi32", - // Extern::typed_func(|_: FuncContext<'_>, x: i32| { - // println!("{}", x); - // Ok(()) - // }), - // )?; - - // let instance = module.instantiate(&mut store, Some(imports))?; - // let add_and_print = instance.typed_func::<(i32, i32), ()>(&mut store, "add_and_print")?; - // add_and_print.call(&mut store, (1, 2))?; + const HELLO_WASM: &[u8] = include_bytes!("./rust/out/hello.wasm"); + let module = Module::parse_bytes(&HELLO_WASM)?; + let mut store = Store::default(); + + let mut imports = Imports::new(); + imports.define( + "env", + "printi32", + Extern::typed_func(|_: FuncContext<'_>, x: i32| { + println!("{}", x); + Ok(()) + }), + )?; + + let instance = module.instantiate(&mut store, Some(imports))?; + let add_and_print = instance.typed_func::<(i32, i32), ()>(&mut store, "add_and_print")?; + add_and_print.call(&mut store, (1, 2))?; Ok(()) } diff --git a/examples/wasm/add.wasm b/examples/wasm/add.wasm deleted file mode 100644 index 92e343278f5bf783a31d603872c2af25cb118d1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65 zcmZQbEY4+QU|?Y6WlCVGuV<`JV5+NQtYc8Nnv1M1CsG(CJc;Rf=uiT O3JeO2S=wl>C*{u#TwFt3E GKgTaC&l%AG diff --git a/examples/wasm/helloworld.wat b/examples/wasm/helloworld.wat deleted file mode 100644 index b74c98f..0000000 --- a/examples/wasm/helloworld.wat +++ /dev/null @@ -1,15 +0,0 @@ -(module - ;; Imports from JavaScript namespace - (import "console" "log" (func $log (param i32 i32))) ;; Import log function - (import "js" "mem" (memory 1)) ;; Import 1 page of memory (54kb) - - ;; Data section of our module - (data (i32.const 0) "Hello World from WebAssembly!") - - ;; Function declaration: Exported as helloWorld(), no arguments - (func (export "helloWorld") - i32.const 0 ;; pass offset 0 to log - i32.const 29 ;; pass length 29 to log (strlen of sample text) - call $log - ) -) \ No newline at end of file diff --git a/examples/wasm/loop.wat b/examples/wasm/loop.wat deleted file mode 100644 index 0dcd191..0000000 --- a/examples/wasm/loop.wat +++ /dev/null @@ -1,84 +0,0 @@ -(module - (func $loop_test (export "loop_test") (result i32) - (local i32) ;; Local 0: Counter - - ;; Initialize the counter - (local.set 0 (i32.const 0)) - - ;; Loop starts here - (loop $my_loop - ;; Increment the counter - (local.set 0 (i32.add (local.get 0) (i32.const 1))) - - ;; Exit condition: break out of the loop if counter >= 10 - (br_if $my_loop (i32.lt_s (local.get 0) (i32.const 10))) - ) - - ;; Return the counter value - (local.get 0) - ) - - (func $loop_test3 (export "loop_test3") (result i32) - (local i32) ;; Local 0: Counter - - ;; Initialize the counter - (local.set 0 (i32.const 0)) - - ;; Loop starts here - (block $exit_loop ;; Label for exiting the loop - (loop $my_loop - ;; Increment the counter - (local.set 0 (i32.add (local.get 0) (i32.const 1))) - - ;; Prepare an index for br_table - ;; Here, we use the counter, but you could modify this - ;; For simplicity, 0 will continue the loop, any other value will exit - (local.get 0) - (i32.const 10) - (i32.lt_s) - (br_table $my_loop $exit_loop) - ) - ) - - ;; Return the counter value - (local.get 0) - ) - - (func $calculate (export "loop_test2") (result i32) - (local i32) ;; Local 0: Counter for the outer loop - (local i32) ;; Local 1: Counter for the inner loop - (local i32) ;; Local 2: Result variable - - ;; Initialize variables - (local.set 0 (i32.const 0)) ;; Initialize outer loop counter - (local.set 1 (i32.const 0)) ;; Initialize inner loop counter - (local.set 2 (i32.const 0)) ;; Initialize result variable - - (block $outer ;; Outer loop label - (loop $outer_loop - (local.set 1 (i32.const 5)) ;; Reset inner loop counter for each iteration of the outer loop - - (block $inner ;; Inner loop label - (loop $inner_loop - (br_if $inner (i32.eqz (local.get 1))) ;; Break to $inner if inner loop counter is zero - - ;; Computation: Adding product of counters to the result - (local.set 2 (i32.add (local.get 2) (i32.mul (local.get 0) (local.get 1)))) - - ;; Decrement inner loop counter - (local.set 1 (i32.sub (local.get 1) (i32.const 1))) - ) - ) - - ;; Increment outer loop counter - (local.set 0 (i32.add (local.get 0) (i32.const 1))) - - ;; Break condition for outer loop: break if outer loop counter >= 5 - (br_if $outer (i32.ge_s (local.get 0) (i32.const 5))) - ) - ) - - ;; Return the result - (local.get 2) - ) -) \ No newline at end of file diff --git a/examples/wasm/test.wat b/examples/wasm/test.wat deleted file mode 100644 index 563f382..0000000 --- a/examples/wasm/test.wat +++ /dev/null @@ -1,7 +0,0 @@ -(module - (func (export "test") (result i32) - (i32.const 1) - ;; comment - (return (i32.const 2)) - ) -) \ No newline at end of file From 133ae7e1f1eb6ccd027a3a0117766551197671f2 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Fri, 26 Jan 2024 12:39:07 +0100 Subject: [PATCH 51/52] chore: fix selfhosting example Signed-off-by: Henry Gressmann --- Cargo.toml | 2 +- examples/rust/src/tinywasm.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b3ed635..33cfdd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members=["crates/*", "examples/rust"] resolver="2" [profile.wasm] -opt-level="z" +opt-level="s" lto="thin" codegen-units=1 panic="abort" diff --git a/examples/rust/src/tinywasm.rs b/examples/rust/src/tinywasm.rs index 52af7b9..0f18ab9 100644 --- a/examples/rust/src/tinywasm.rs +++ b/examples/rust/src/tinywasm.rs @@ -12,7 +12,7 @@ pub extern "C" fn hello() { } fn run() -> tinywasm::Result<()> { - let module = tinywasm::Module::parse_bytes(include_bytes!("../../wasm/hello.wasm"))?; + let module = tinywasm::Module::parse_bytes(include_bytes!("../out/hello.wasm"))?; let mut store = tinywasm::Store::default(); let mut imports = tinywasm::Imports::new(); From 67f0fd68f1f60f0629d997d5181e5e06440258d7 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Fri, 26 Jan 2024 12:39:34 +0100 Subject: [PATCH 52/52] Release 0.3.0 tinywasm@0.3.0 tinywasm-cli@0.3.0 tinywasm-parser@0.3.0 tinywasm-types@0.3.0 wasm-testsuite@0.2.1 Generated by cargo-workspaces --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- crates/wasm-testsuite/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbd82db..b145eff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1254,7 +1254,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tinywasm" -version = "0.3.0-alpha.0" +version = "0.3.0" dependencies = [ "eyre", "libm", @@ -1272,7 +1272,7 @@ dependencies = [ [[package]] name = "tinywasm-cli" -version = "0.3.0-alpha.0" +version = "0.3.0" dependencies = [ "argh", "color-eyre", @@ -1284,7 +1284,7 @@ dependencies = [ [[package]] name = "tinywasm-parser" -version = "0.3.0-alpha.0" +version = "0.3.0" dependencies = [ "log", "tinywasm-types", @@ -1301,7 +1301,7 @@ dependencies = [ [[package]] name = "tinywasm-types" -version = "0.3.0-alpha.0" +version = "0.3.0" dependencies = [ "log", "rkyv", @@ -1471,7 +1471,7 @@ dependencies = [ [[package]] name = "wasm-testsuite" -version = "0.2.0" +version = "0.2.1" dependencies = [ "rust-embed", ] diff --git a/Cargo.toml b/Cargo.toml index 33cfdd1..ee9a9df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ panic="abort" inherits="release" [workspace.package] -version="0.3.0-alpha.0" +version="0.3.0" edition="2021" license="MIT OR Apache-2.0" authors=["Henry Gressmann "] diff --git a/crates/wasm-testsuite/Cargo.toml b/crates/wasm-testsuite/Cargo.toml index 3e6d647..04f478c 100644 --- a/crates/wasm-testsuite/Cargo.toml +++ b/crates/wasm-testsuite/Cargo.toml @@ -1,6 +1,6 @@ [package] name="wasm-testsuite" -version="0.2.0" +version="0.2.1" description="Mirror of the WebAssembly core testsuite for use in testing WebAssembly implementations" license="Apache-2.0" readme="README.md"