Skip to content

Commit

Permalink
Refactor how wasm features are calculated for *.wast tests (bytecod…
Browse files Browse the repository at this point in the history
…ealliance#9560)

* Refactor how wasm features are calculated for `*.wast` tests

This commit refactors the `tests/wast.rs` test suite which runs all of
the upstream spec tests as `*.wast` files as well as our own
`misc_testsuite` which has its own suite of `*.wast` files. Previously
the set of wasm features active for each test was a sort of random
mishmash and convoluted set of conditionals which was updated and edited
over time as upstream proposal test suites evolved. This was then
mirrored into our own conventions for `misc_testsuite` as well. Overall
though this has a number of downsides I'm trying to fix here:

* The calculation of what features are enabled is quite complicated and
  effectively a random mishmash of `||` conditionals with hierarchies
  that don't make any sense beyond "this is just required to get things
  to pass".

* There is no means of per-test configuration. For example
  `canonicalize-nans.wast` had hardcoded logic in `tests/wast.rs` that
  it needed a different setting turned on in `Config`.

* There was no easy means to write tests for Wasmtime which take a union
  of a number of proposals together without having lots of sub-folders
  that may not make sense.

* Tests that require a particular proposal had to have duplicate logic
  for Winch as it doesn't support the full suite of features of all
  proposals that Cranelift does.

The new system implemented in this commit takes a leaf out of the
`disas` tests. There is a new `TestConfig` structure in the
`tests/wast.rs` harness which is decoded from each test (leading `;;!`
comments) which enables specifying, in each test, what's required. This
encompasses many wasm proposals but additionally captures other behavior
like nan-canonicalization. This means that all test files in
`misc_testsuite/**/*.wast` are now manually annotated with what wasm
features they require and what's needed to run. This makes per-test
configuration much easier, per-config-setting much easier, and blanket
ignore-by-proposal for Winch much easier as well.

For spec tests we can't modify the contents of the upstream `*.wast`
files. To handle this they're handled specially where `TestConfig` is
manually created and manipulated for each spec proposal and the main
test suite itself. This enables per-proposal configuration that doesn't
leak into any others and makes it more obvious what proposals are doing
what.

* Hack around Winch support for aarch64
  • Loading branch information
alexcrichton authored Nov 5, 2024
1 parent 65181b3 commit 60fc557
Show file tree
Hide file tree
Showing 71 changed files with 370 additions and 101 deletions.
23 changes: 3 additions & 20 deletions tests/disas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ use cranelift_codegen::isa::{lookup_by_name, TargetIsa};
use cranelift_codegen::settings::{Configurable, Flags, SetError};
use libtest_mimic::{Arguments, Trial};
use pulley_interpreter::decode::OpVisitor;
use serde::de::DeserializeOwned;
use serde_derive::Deserialize;
use similar::TextDiff;
use std::fmt::Write;
Expand All @@ -56,6 +55,8 @@ use tempfile::TempDir;
use wasmtime::{Engine, OptLevel, Strategy};
use wasmtime_cli_flags::CommonOptions;

mod support;

fn main() -> Result<()> {
if cfg!(miri) {
return Ok(());
Expand Down Expand Up @@ -152,7 +153,7 @@ impl Test {
fn new(path: &Path) -> Result<Test> {
let contents =
std::fs::read_to_string(path).with_context(|| format!("failed to read {path:?}"))?;
let config: TestConfig = Test::parse_test_config(&contents)
let config: TestConfig = support::parse_test_config(&contents)
.context("failed to parse test configuration as TOML")?;
let mut flags = vec!["wasmtime"];
match &config.flags {
Expand All @@ -170,24 +171,6 @@ impl Test {
})
}

/// Parse test configuration from the specified test, comments starting with
/// `;;!`.
fn parse_test_config<T>(wat: &str) -> Result<T>
where
T: DeserializeOwned,
{
// The test config source is the leading lines of the WAT file that are
// prefixed with `;;!`.
let config_lines: Vec<_> = wat
.lines()
.take_while(|l| l.starts_with(";;!"))
.map(|l| &l[3..])
.collect();
let config_text = config_lines.join("\n");

toml::from_str(&config_text).context("failed to parse the test configuration")
}

/// Generates CLIF for all the wasm functions in this test.
fn compile(&mut self) -> Result<CompileOutput> {
// Use wasmtime::Config with its `emit_clif` option to get Wasmtime's
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/component-model/adapter.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! multi_memory = true

;; basic function lifting
(component
(core module $m
Expand Down
3 changes: 3 additions & 0 deletions tests/misc_testsuite/component-model/fused.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
;;! multi_memory = true
;;! component_model_more_flags = true

;; smoke test with no arguments and no results
(component
(core module $m
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/component-model/modules.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(component $foo
(core module (export "a-module"))
)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/component-model/strings.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! multi_memory = true

;; unaligned utf16 string
(assert_trap
(component
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
;;! custom_page_sizes = true
;;! multi_memory = true

;; Page size that is not a power of two.
(assert_malformed
(module quote "(memory 0 (pagesize 3))")
Expand Down
3 changes: 3 additions & 0 deletions tests/misc_testsuite/custom-page-sizes/custom-page-sizes.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
;;! custom_page_sizes = true
;;! multi_memory = true

;; Check all the valid custom page sizes.
(module (memory 1 (pagesize 1)))
(module (memory 1 (pagesize 65536)))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/elem-ref-null.wast
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
;;! reference_types = true

(module
(elem funcref (ref.null func)))
2 changes: 2 additions & 0 deletions tests/misc_testsuite/elem_drop.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module
(table 1 1 funcref)
(elem (i32.const 0) funcref (ref.func 0))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/externref-id-function.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module
(func (export "identity") (param externref) (result externref)
local.get 0))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/externref-segment.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module
(table 2 externref)
(elem (i32.const 0) externref (ref.null extern))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module
(table $t 0 0 externref)

Expand Down
3 changes: 3 additions & 0 deletions tests/misc_testsuite/function-references/call_indirect.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
;;! gc = true
;;! function_references = true

(module
(table $t1 2 funcref)
(elem (table $t1) (i32.const 0) func $nop)
Expand Down
3 changes: 3 additions & 0 deletions tests/misc_testsuite/function-references/instance.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
;;! gc = true
;;! multi_memory = true

;; Instantiation is generative

(module definition $M
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/function-references/table_fill.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(table $t 10 externref)

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/function-references/table_get.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(type $res-i32 (func (result i32)))
(table $t2 2 externref)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/function-references/table_grow.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(table $t 0 externref)

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/function-references/table_set.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(type $res-i32 (func (result i32)))
(table $t2 1 externref)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/anyref_that_is_i31_barriers.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

;; Test that our inline GC barriers detect `i31`s and don't attempt to actually
;; deref them or anything like that.

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/array-alloc-too-large.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(type $arr_i8 (array i8))
(type $arr_i64 (array i64))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/array-init-data.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(type $arr (array (mut i8)))

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/array-new-data.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(type $arr (array (mut i8)))

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/array-new-elem.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(type $arr (array i31ref))

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/array-types.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(type (array i8))
(type (array i16))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/func-refs-in-gc-heap.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(type $f0 (func (result i32)))

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/i31ref-of-global-initializers.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module $env
(global (export "g1") i32 (i32.const 42))
(global (export "g2") i32 (i32.const 99))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/i31ref-tables.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module $tables_of_i31ref
(table $table 3 10 i31ref)
(elem (table $table) (i32.const 0) i31ref (item (ref.i31 (i32.const 999)))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/more-rec-groups-than-types.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

;; Test that we properly handle empty rec groups and when we have more rec
;; groups defined in the type section than actual types (and therefore the
;; length that the type section reports is greater than the length of the types
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/null-i31ref.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(func (export "get_u-null") (result i32)
(i31.get_u (ref.null i31))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/rec-group-funcs.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

;; Test that we properly canonicalize function types across modules, at the
;; engine level. We rely on this canonicalization to make cross-module imports
;; work among other things.
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/ref-test.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(func (export "nulls-to-nullable-tops") (result i32)
(ref.test anyref (ref.null any))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/struct-instructions.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(type $ty (struct (field (mut f32))
(field (mut i8))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/gc/struct-types.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! gc = true

(module
(type (struct))
(type (struct (field)))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/linking-errors.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module $m
(global (export "g i32") i32 (i32.const 0))
(global (export "g mut i32") (mut i32) (i32.const 0))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/many_table_gets_lead_to_gc.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module
(table $t 1 externref)

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/memory64/bounds.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! memory64 = true

(assert_unlinkable
(module
(memory i64 1)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/memory64/codegen.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! memory64 = true

;; make sure everything codegens correctly and has no cranelift verifier errors
(module
(memory i64 1)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/memory64/linking-errors.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! memory64 = true

(module $m
(memory (export "mem") 0)
)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/memory64/linking.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! memory64 = true

(module $export32 (memory (export "m") 1))
(module $export64 (memory (export "m") i64 1))

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/memory64/more-than-4gb.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! memory64 = true

;; try to create as few 4gb memories as we can to reduce the memory consumption
;; of this test, so create one up front here and use it below.
(module $memory
Expand Down
3 changes: 3 additions & 0 deletions tests/misc_testsuite/memory64/multi-memory.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
;;! memory64 = true
;;! multi_memory = true

;; 64 => 64
(module
(memory $a i64 1)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/memory64/offsets.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! memory64 = true

(module
(memory i64 1)
(func (export "load1") (result i32)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/memory64/simd.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! memory64 = true

;; make sure everything codegens correctly and has no cranelift verifier errors
(module
(memory i64 1)
Expand Down
3 changes: 3 additions & 0 deletions tests/misc_testsuite/memory64/threads.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
;;! memory64 = true
;;! threads = true

;; make sure everything codegens correctly and has no cranelift verifier errors
(module
(memory i64 1)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/multi-memory/simple.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! multi_memory = true

(module
(memory $m1 1)
(memory $m2 1)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/mutable_externref_globals.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

;; This test contains the changes in
;; https://github.com/WebAssembly/reference-types/pull/104, and can be deleted
;; once that merges and we update our upstream tests.
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/no-mixup-stack-maps.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module
(global $g (mut externref) (ref.null extern))

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/no-panic.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module
(func $test (param i32) (result externref)
i32.const 0
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/simd/canonicalize-nan.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! nan_canonicalization = true

;; This *.wast test should be run with `cranelift_nan_canonicalization` set to
;; `true` in `wast.rs`

Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/simple_ref_is_null.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module
(func (export "func_is_null") (param funcref) (result i32)
(ref.is_null (local.get 0))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/table_copy_on_imported_tables.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module $m
(func $f (param i32 i32 i32 i32 i32 i32) (result i32) (local.get 0))
(func $g (param i32 i32 i32 i32 i32 i32) (result i32) (local.get 1))
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/table_grow_with_funcref.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! reference_types = true

(module
(table $t 0 funcref)
(func (export "size") (result i32)
Expand Down
3 changes: 3 additions & 0 deletions tests/misc_testsuite/tail-call/loop-across-modules.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
;;! tail_call = true
;;! reference_types = true

;; Do the following loop: `A.f` indirect tail calls through the table, which is
;; populated by `B.start` to contain `B.g`, which in turn tail calls `A.f` and
;; the loop begins again.
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/threads/LB.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! threads = true

(module $Mem
(memory (export "shared") 1 1 shared)
)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/threads/LB_atomic.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! threads = true

(module $Mem
(memory (export "shared") 1 1 shared)
)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/threads/MP.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! threads = true

(module $Mem
(memory (export "shared") 1 1 shared)
)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/threads/MP_atomic.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! threads = true

(module $Mem
(memory (export "shared") 1 1 shared)
)
Expand Down
2 changes: 2 additions & 0 deletions tests/misc_testsuite/threads/MP_wait.wast
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;;! threads = true

(module $Mem
(memory (export "shared") 1 1 shared)
)
Expand Down
Loading

0 comments on commit 60fc557

Please sign in to comment.