Skip to content

Commit 35053d6

Browse files
authored
winch(aarch64): Run wast test in CI (#10750)
* winch(aarch64): Run wast test in CI Closes #9566 This commit takes inspiration from https://github.com/bytecodealliance/wasmtime/pull/10738/files During the 2025-05-07 Cranelift meeting we discussed potential avenues to start running wast tests for winch-aarch64. One potential idea was to declare an allowlist of tests that should be exectued and potentially ignore everyhing else. Although that idea works, I decided to diverge a bit from it, in favor of introducing a very strict classification of the state of tests for aarch64, namely, in this commit tests are classified as: * Run and expected to pass * Run and exepected to fail in a recoverable way * Don't run since it's known that they produce an unrecoverable error e.g., segafault. This approach is probably more verbose than the one discussed in the meeting, however, I think it's easier to have a global view of that status for aarch64 and potentially other backends in the future. * Formatting * Extract common tests that fail in all targets * Move the `Compiler::should_fail` call at runtime `Compiler::should_fail` makes use of `#[cfg(target_arg="...")]` directives to derive the compiler-arch-Wasm proposal support matrix, however, `Compiler::should_fail` is also called from the `wasmtime_test` macro which introduces conflicts with the `target_arch` resolution (within macros, these directives resolve to the host compiler, instead of the target). This commit emits `Compiler::should_fail` at runtime instead of at compile time, which fixes the issue mentioned above. * Use `.unwrap` when test is expected to pass
1 parent 7a27724 commit 35053d6

File tree

6 files changed

+234
-135
lines changed

6 files changed

+234
-135
lines changed

crates/test-macros/src/wasmtime_test.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,21 +253,17 @@ fn expand(test_config: &TestConfig, func: Fn) -> Result<TokenStream> {
253253
(quote! {}, quote! {})
254254
};
255255
let func_name = &func.sig.ident;
256-
let expect = match &func.sig.output {
257-
ReturnType::Default => quote! {},
258-
ReturnType::Type(..) => quote! { .expect("test is expected to pass") },
256+
match &func.sig.output {
257+
ReturnType::Default => {
258+
return Err(syn::Error::new(func_name.span(), "Expected `Restult<()>`"))
259+
}
260+
ReturnType::Type(..) => {}
259261
};
260262
let test_name = Ident::new(
261263
&format!("{}_{}", strategy_name.to_lowercase(), func_name),
262264
func_name.span(),
263265
);
264266

265-
let should_panic = if strategy.should_fail(&test_config.flags) {
266-
quote!(#[should_panic])
267-
} else {
268-
quote!()
269-
};
270-
271267
let test_config = format!("wasmtime_test_util::wast::{:?}", test_config.flags)
272268
.parse::<proc_macro2::TokenStream>()
273269
.unwrap();
@@ -276,7 +272,6 @@ fn expand(test_config: &TestConfig, func: Fn) -> Result<TokenStream> {
276272
let tok = quote! {
277273
#test_attr
278274
#target
279-
#should_panic
280275
#(#attrs)*
281276
#asyncness fn #test_name() {
282277
let _ = env_logger::try_init();
@@ -293,7 +288,12 @@ fn expand(test_config: &TestConfig, func: Fn) -> Result<TokenStream> {
293288
collector: wasmtime_test_util::wast::Collector::Auto,
294289
},
295290
);
296-
#func_name(&mut config) #await_ #expect
291+
let result = #func_name(&mut config) #await_;
292+
if wasmtime_test_util::wast::Compiler::#strategy_ident.should_fail(&#test_config) {
293+
assert!(result.is_err());
294+
} else {
295+
result.unwrap();
296+
}
297297
}
298298
};
299299

crates/test-util/src/wast.rs

Lines changed: 184 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -341,14 +341,27 @@ impl Compiler {
341341
Compiler::CraneliftNative => config.legacy_exceptions(),
342342

343343
Compiler::Winch => {
344-
config.gc()
344+
let unsupported_base = config.gc()
345345
|| config.tail_call()
346346
|| config.function_references()
347347
|| config.gc()
348348
|| config.relaxed_simd()
349349
|| config.gc_types()
350350
|| config.exceptions()
351-
|| config.legacy_exceptions()
351+
|| config.legacy_exceptions();
352+
353+
if cfg!(target_arch = "x86_64") {
354+
return unsupported_base;
355+
}
356+
357+
if cfg!(target_arch = "aarch64") {
358+
return unsupported_base
359+
|| config.simd()
360+
|| config.wide_arithmetic()
361+
|| config.threads();
362+
}
363+
364+
false
352365
}
353366

354367
Compiler::CraneliftPulley => config.threads() || config.legacy_exceptions(),
@@ -365,9 +378,7 @@ impl Compiler {
365378
|| cfg!(target_arch = "riscv64")
366379
|| cfg!(target_arch = "s390x")
367380
}
368-
Compiler::Winch => {
369-
cfg!(target_arch = "x86_64")
370-
}
381+
Compiler::Winch => cfg!(target_arch = "x86_64") || cfg!(target_arch = "aarch64"),
371382
Compiler::CraneliftPulley => true,
372383
}
373384
}
@@ -392,6 +403,51 @@ impl WastTest {
392403
spec_proposal_from_path(&self.path)
393404
}
394405

406+
/// Returns true for tests that should be ignored (not run) for
407+
/// the given config.
408+
409+
/// The infrastructure for `.wast` tests is designed to enable the
410+
/// execution of tests at all times, however, while compiler
411+
/// backends are in partial development state, it becomes harder
412+
/// to guarantee particular tests will run to completion and
413+
/// return a recoverable error, in some cases tests might segfault
414+
/// making it challenging to assert a failure status.
415+
/// It's recommended to avoid ignoring tests as much as possible, instead
416+
/// it's recommended to add tests to `WastTest::should_fail`.
417+
pub fn ignore(&self, config: &WastConfig) -> bool {
418+
if config.compiler == Compiler::Winch {
419+
if cfg!(target_arch = "aarch64") {
420+
let unsupported = [
421+
// Missing stack checks (#8321)
422+
"spec_testsuite/call.wast",
423+
"spec_testsuite/fac.wast",
424+
"spec_testsuite/skip-stack-guard-page.wast",
425+
"misc_testsuite/stack_overflow.wast",
426+
// Fails intermittently
427+
"misc_testsuite/table_copy_on_imported_tables.wast",
428+
// Segfault
429+
"spec_testsuite/conversions.wast",
430+
"spec_testsuite/func.wast",
431+
"spec_testsuite/float_exprs.wast",
432+
"spec_testsuite/int_exprs.wast",
433+
"spec_testsuite/left-to-right.wast",
434+
"spec_testsuite/i32.wast",
435+
"spec_testsuite/traps.wast",
436+
"spec_testsuite/unreachable.wast",
437+
"spec_testsuite/unreached-valid.wast",
438+
"misc_testsuite/component-model/fused.wast",
439+
"misc_testsuite/component-model/strings.wast",
440+
"misc_testsuite/winch/select.wast",
441+
"misc_testsuite/sink-float-but-dont-trap.wast",
442+
"misc_testsuite/issue4840.wast",
443+
];
444+
445+
return unsupported.iter().any(|part| self.path.ends_with(part));
446+
}
447+
}
448+
false
449+
}
450+
395451
/// Returns whether this test should fail under the specified extra
396452
/// configuration.
397453
pub fn should_fail(&self, config: &WastConfig) -> bool {
@@ -430,13 +486,13 @@ impl WastTest {
430486
return true;
431487
}
432488

433-
// Disable spec tests for proposals that Winch does not implement yet.
489+
// Disable spec tests per target for proposals that Winch does not implement yet.
434490
if config.compiler == Compiler::Winch {
491+
// Common list for tests that fail in all targets supported by Winch.
435492
let unsupported = [
436-
// externref/reference-types related
437-
"component-model/modules.wast",
438493
"extended-const/elem.wast",
439494
"extended-const/global.wast",
495+
"misc_testsuite/component-model/modules.wast",
440496
"misc_testsuite/externref-id-function.wast",
441497
"misc_testsuite/externref-segment.wast",
442498
"misc_testsuite/externref-segments.wast",
@@ -449,10 +505,7 @@ impl WastTest {
449505
"misc_testsuite/simple_ref_is_null.wast",
450506
"misc_testsuite/table_grow_with_funcref.wast",
451507
"spec_testsuite/br_table.wast",
452-
"spec_testsuite/data-invalid.wast",
453-
"spec_testsuite/elem.wast",
454508
"spec_testsuite/global.wast",
455-
"spec_testsuite/linking.wast",
456509
"spec_testsuite/ref_func.wast",
457510
"spec_testsuite/ref_is_null.wast",
458511
"spec_testsuite/ref_null.wast",
@@ -462,93 +515,139 @@ impl WastTest {
462515
"spec_testsuite/table_grow.wast",
463516
"spec_testsuite/table_set.wast",
464517
"spec_testsuite/table_size.wast",
465-
// simd-related failures
466-
"misc_testsuite/simd/canonicalize-nan.wast",
518+
"spec_testsuite/elem.wast",
519+
"spec_testsuite/linking.wast",
467520
];
468521

469522
if unsupported.iter().any(|part| self.path.ends_with(part)) {
470523
return true;
471524
}
472525

473-
// SIMD on Winch requires AVX instructions.
526+
#[cfg(target_arch = "aarch64")]
527+
{
528+
let unsupported = [
529+
// Externref / GC related.
530+
"misc_testsuite/winch/table_get.wast",
531+
"misc_testsuite/winch/table_set.wast",
532+
"misc_testsuite/winch/table_fill.wast",
533+
// Known bugs that don't cause segfaults.
534+
"spec_testsuite/call_indirect.wast",
535+
"spec_testsuite/f32_cmp.wast",
536+
"spec_testsuite/f64_cmp.wast",
537+
"spec_testsuite/func_ptrs.wast",
538+
"spec_testsuite/i64.wast",
539+
"spec_testsuite/if.wast",
540+
"spec_testsuite/imports.wast",
541+
"spec_testsuite/local_set.wast",
542+
"spec_testsuite/local_tee.wast",
543+
"spec_testsuite/loop.wast",
544+
"spec_testsuite/table_copy.wast",
545+
"spec_testsuite/table_init.wast",
546+
"misc_testsuite/custom-page-sizes/custom-page-sizes.wast",
547+
"misc_testsuite/winch/table_grow.wast",
548+
"spec_testsuite/proposals/custom-page-sizes/custom-page-sizes.wast",
549+
"misc_testsuite/memory64/more-than-4gb.wast",
550+
"misc_testsuite/call_indirect.wast",
551+
];
552+
553+
if unsupported.iter().any(|part| self.path.ends_with(part)) {
554+
return true;
555+
}
556+
}
557+
474558
#[cfg(target_arch = "x86_64")]
475-
if !(std::is_x86_feature_detected!("avx") && std::is_x86_feature_detected!("avx2")) {
559+
{
476560
let unsupported = [
477-
"annotations/simd_lane.wast",
478-
"memory64/simd.wast",
479-
"misc_testsuite/int-to-float-splat.wast",
480-
"misc_testsuite/issue6562.wast",
481-
"misc_testsuite/simd/almost-extmul.wast",
482-
"misc_testsuite/simd/cvt-from-uint.wast",
483-
"misc_testsuite/simd/issue_3327_bnot_lowering.wast",
484-
"misc_testsuite/simd/issue6725-no-egraph-panic.wast",
485-
"misc_testsuite/simd/replace-lane-preserve.wast",
486-
"misc_testsuite/simd/spillslot-size-fuzzbug.wast",
487-
"misc_testsuite/winch/issue-10331.wast",
488-
"misc_testsuite/winch/replace_lane.wast",
489-
"spec_testsuite/simd_align.wast",
490-
"spec_testsuite/simd_boolean.wast",
491-
"spec_testsuite/simd_conversions.wast",
492-
"spec_testsuite/simd_f32x4.wast",
493-
"spec_testsuite/simd_f32x4_arith.wast",
494-
"spec_testsuite/simd_f32x4_cmp.wast",
495-
"spec_testsuite/simd_f32x4_pmin_pmax.wast",
496-
"spec_testsuite/simd_f32x4_rounding.wast",
497-
"spec_testsuite/simd_f64x2.wast",
498-
"spec_testsuite/simd_f64x2_arith.wast",
499-
"spec_testsuite/simd_f64x2_cmp.wast",
500-
"spec_testsuite/simd_f64x2_pmin_pmax.wast",
501-
"spec_testsuite/simd_f64x2_rounding.wast",
502-
"spec_testsuite/simd_i16x8_cmp.wast",
503-
"spec_testsuite/simd_i32x4_cmp.wast",
504-
"spec_testsuite/simd_i64x2_arith2.wast",
505-
"spec_testsuite/simd_i64x2_cmp.wast",
506-
"spec_testsuite/simd_i8x16_arith2.wast",
507-
"spec_testsuite/simd_i8x16_cmp.wast",
508-
"spec_testsuite/simd_int_to_int_extend.wast",
509-
"spec_testsuite/simd_load.wast",
510-
"spec_testsuite/simd_load_extend.wast",
511-
"spec_testsuite/simd_load_splat.wast",
512-
"spec_testsuite/simd_load_zero.wast",
513-
"spec_testsuite/simd_splat.wast",
514-
"spec_testsuite/simd_store16_lane.wast",
515-
"spec_testsuite/simd_store32_lane.wast",
516-
"spec_testsuite/simd_store64_lane.wast",
517-
"spec_testsuite/simd_store8_lane.wast",
518-
"spec_testsuite/simd_load16_lane.wast",
519-
"spec_testsuite/simd_load32_lane.wast",
520-
"spec_testsuite/simd_load64_lane.wast",
521-
"spec_testsuite/simd_load8_lane.wast",
522-
"spec_testsuite/simd_bitwise.wast",
523-
"misc_testsuite/simd/load_splat_out_of_bounds.wast",
524-
"misc_testsuite/simd/unaligned-load.wast",
525-
"multi-memory/simd_memory-multi.wast",
526-
"misc_testsuite/simd/issue4807.wast",
527-
"spec_testsuite/simd_const.wast",
528-
"spec_testsuite/simd_i8x16_sat_arith.wast",
529-
"spec_testsuite/simd_i64x2_arith.wast",
530-
"spec_testsuite/simd_i16x8_arith.wast",
531-
"spec_testsuite/simd_i16x8_arith2.wast",
532-
"spec_testsuite/simd_i16x8_q15mulr_sat_s.wast",
533-
"spec_testsuite/simd_i16x8_sat_arith.wast",
534-
"spec_testsuite/simd_i32x4_arith.wast",
535-
"spec_testsuite/simd_i32x4_dot_i16x8.wast",
536-
"spec_testsuite/simd_i32x4_trunc_sat_f32x4.wast",
537-
"spec_testsuite/simd_i32x4_trunc_sat_f64x2.wast",
538-
"spec_testsuite/simd_i8x16_arith.wast",
539-
"spec_testsuite/simd_bit_shift.wast",
540-
"spec_testsuite/simd_lane.wast",
541-
"spec_testsuite/simd_i16x8_extmul_i8x16.wast",
542-
"spec_testsuite/simd_i32x4_extmul_i16x8.wast",
543-
"spec_testsuite/simd_i64x2_extmul_i32x4.wast",
544-
"spec_testsuite/simd_i16x8_extadd_pairwise_i8x16.wast",
545-
"spec_testsuite/simd_i32x4_extadd_pairwise_i16x8.wast",
546-
"spec_testsuite/simd_i32x4_arith2.wast",
561+
// externref/reference-types related
562+
// simd-related failures
563+
"misc_testsuite/simd/canonicalize-nan.wast",
547564
];
548565

549566
if unsupported.iter().any(|part| self.path.ends_with(part)) {
550567
return true;
551568
}
569+
570+
// SIMD on Winch requires AVX instructions.
571+
#[cfg(target_arch = "x86_64")]
572+
if !(std::is_x86_feature_detected!("avx") && std::is_x86_feature_detected!("avx2"))
573+
{
574+
let unsupported = [
575+
"annotations/simd_lane.wast",
576+
"memory64/simd.wast",
577+
"misc_testsuite/int-to-float-splat.wast",
578+
"misc_testsuite/issue6562.wast",
579+
"misc_testsuite/simd/almost-extmul.wast",
580+
"misc_testsuite/simd/cvt-from-uint.wast",
581+
"misc_testsuite/simd/issue_3327_bnot_lowering.wast",
582+
"misc_testsuite/simd/issue6725-no-egraph-panic.wast",
583+
"misc_testsuite/simd/replace-lane-preserve.wast",
584+
"misc_testsuite/simd/spillslot-size-fuzzbug.wast",
585+
"misc_testsuite/winch/issue-10331.wast",
586+
"misc_testsuite/winch/replace_lane.wast",
587+
"spec_testsuite/simd_align.wast",
588+
"spec_testsuite/simd_boolean.wast",
589+
"spec_testsuite/simd_conversions.wast",
590+
"spec_testsuite/simd_f32x4.wast",
591+
"spec_testsuite/simd_f32x4_arith.wast",
592+
"spec_testsuite/simd_f32x4_cmp.wast",
593+
"spec_testsuite/simd_f32x4_pmin_pmax.wast",
594+
"spec_testsuite/simd_f32x4_rounding.wast",
595+
"spec_testsuite/simd_f64x2.wast",
596+
"spec_testsuite/simd_f64x2_arith.wast",
597+
"spec_testsuite/simd_f64x2_cmp.wast",
598+
"spec_testsuite/simd_f64x2_pmin_pmax.wast",
599+
"spec_testsuite/simd_f64x2_rounding.wast",
600+
"spec_testsuite/simd_i16x8_cmp.wast",
601+
"spec_testsuite/simd_i32x4_cmp.wast",
602+
"spec_testsuite/simd_i64x2_arith2.wast",
603+
"spec_testsuite/simd_i64x2_cmp.wast",
604+
"spec_testsuite/simd_i8x16_arith2.wast",
605+
"spec_testsuite/simd_i8x16_cmp.wast",
606+
"spec_testsuite/simd_int_to_int_extend.wast",
607+
"spec_testsuite/simd_load.wast",
608+
"spec_testsuite/simd_load_extend.wast",
609+
"spec_testsuite/simd_load_splat.wast",
610+
"spec_testsuite/simd_load_zero.wast",
611+
"spec_testsuite/simd_splat.wast",
612+
"spec_testsuite/simd_store16_lane.wast",
613+
"spec_testsuite/simd_store32_lane.wast",
614+
"spec_testsuite/simd_store64_lane.wast",
615+
"spec_testsuite/simd_store8_lane.wast",
616+
"spec_testsuite/simd_load16_lane.wast",
617+
"spec_testsuite/simd_load32_lane.wast",
618+
"spec_testsuite/simd_load64_lane.wast",
619+
"spec_testsuite/simd_load8_lane.wast",
620+
"spec_testsuite/simd_bitwise.wast",
621+
"misc_testsuite/simd/load_splat_out_of_bounds.wast",
622+
"misc_testsuite/simd/unaligned-load.wast",
623+
"multi-memory/simd_memory-multi.wast",
624+
"misc_testsuite/simd/issue4807.wast",
625+
"spec_testsuite/simd_const.wast",
626+
"spec_testsuite/simd_i8x16_sat_arith.wast",
627+
"spec_testsuite/simd_i64x2_arith.wast",
628+
"spec_testsuite/simd_i16x8_arith.wast",
629+
"spec_testsuite/simd_i16x8_arith2.wast",
630+
"spec_testsuite/simd_i16x8_q15mulr_sat_s.wast",
631+
"spec_testsuite/simd_i16x8_sat_arith.wast",
632+
"spec_testsuite/simd_i32x4_arith.wast",
633+
"spec_testsuite/simd_i32x4_dot_i16x8.wast",
634+
"spec_testsuite/simd_i32x4_trunc_sat_f32x4.wast",
635+
"spec_testsuite/simd_i32x4_trunc_sat_f64x2.wast",
636+
"spec_testsuite/simd_i8x16_arith.wast",
637+
"spec_testsuite/simd_bit_shift.wast",
638+
"spec_testsuite/simd_lane.wast",
639+
"spec_testsuite/simd_i16x8_extmul_i8x16.wast",
640+
"spec_testsuite/simd_i32x4_extmul_i16x8.wast",
641+
"spec_testsuite/simd_i64x2_extmul_i32x4.wast",
642+
"spec_testsuite/simd_i16x8_extadd_pairwise_i8x16.wast",
643+
"spec_testsuite/simd_i32x4_extadd_pairwise_i16x8.wast",
644+
"spec_testsuite/simd_i32x4_arith2.wast",
645+
];
646+
647+
if unsupported.iter().any(|part| self.path.ends_with(part)) {
648+
return true;
649+
}
650+
}
552651
}
553652
}
554653

0 commit comments

Comments
 (0)