From e106d63516b7e1a75c3e2e8873ac805b8833b192 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 12 Feb 2025 03:48:20 +0000 Subject: [PATCH] Add a way to print inputs on failure When there is a panic in an extensive test, tracing down where it came from can be difficult since no information is provides (messeges are e.g. "attempted to subtract with overflow"). Resolve this by calling the functions within `panic::catch_unwind`, printing the input, and continuing. --- .../libm/crates/libm-test/src/op.rs | 6 ++++-- .../libm/crates/libm-test/src/test_traits.rs | 19 ++++++++++++++++++- .../libm-test/tests/compare_built_musl.rs | 2 +- .../crates/libm-test/tests/multiprecision.rs | 2 +- .../libm/crates/libm-test/tests/standalone.rs | 2 +- .../crates/libm-test/tests/z_extensive/run.rs | 2 +- .../libm/crates/util/src/main.rs | 2 +- 7 files changed, 27 insertions(+), 8 deletions(-) diff --git a/library/compiler-builtins/libm/crates/libm-test/src/op.rs b/library/compiler-builtins/libm/crates/libm-test/src/op.rs index 239c9a3e1fdf..47d72ae58b39 100644 --- a/library/compiler-builtins/libm/crates/libm-test/src/op.rs +++ b/library/compiler-builtins/libm/crates/libm-test/src/op.rs @@ -14,6 +14,7 @@ //! level. `Op` is also used as the name for generic parameters since it is terse. use std::fmt; +use std::panic::{RefUnwindSafe, UnwindSafe}; pub use shared::{ALL_OPERATIONS, FloatTy, MathOpInfo, Ty}; @@ -64,7 +65,7 @@ pub trait MathOp { type CRet; /// The signature of the Rust function as a `fn(...) -> ...` type. - type RustFn: Copy; + type RustFn: Copy + UnwindSafe; /// Arguments passed to the Rust library function as a tuple. /// @@ -72,7 +73,8 @@ pub trait MathOp { /// to the Rust function. type RustArgs: Copy + TupleCall - + TupleCall; + + TupleCall + + RefUnwindSafe; /// Type returned from the Rust function. type RustRet: CheckOutput; diff --git a/library/compiler-builtins/libm/crates/libm-test/src/test_traits.rs b/library/compiler-builtins/libm/crates/libm-test/src/test_traits.rs index bba1fca64e6f..c560dade8848 100644 --- a/library/compiler-builtins/libm/crates/libm-test/src/test_traits.rs +++ b/library/compiler-builtins/libm/crates/libm-test/src/test_traits.rs @@ -6,7 +6,8 @@ //! - `CheckOutput`: implemented on anything that is an output type for validation against an //! expected value. -use std::fmt; +use std::panic::{RefUnwindSafe, UnwindSafe}; +use std::{fmt, panic}; use anyhow::{Context, anyhow, bail, ensure}; use libm::support::Hexf; @@ -23,6 +24,22 @@ use crate::{ pub trait TupleCall: fmt::Debug { type Output; fn call(self, f: Func) -> Self::Output; + + /// Intercept panics and print the input to stderr before continuing. + fn call_intercept_panics(self, f: Func) -> Self::Output + where + Self: RefUnwindSafe + Copy, + Func: UnwindSafe, + { + let res = panic::catch_unwind(|| self.call(f)); + match res { + Ok(v) => v, + Err(e) => { + eprintln!("panic with the following input: {self:?}"); + panic::resume_unwind(e) + } + } + } } /// A trait to implement on any output type so we can verify it in a generic way. diff --git a/library/compiler-builtins/libm/crates/libm-test/tests/compare_built_musl.rs b/library/compiler-builtins/libm/crates/libm-test/tests/compare_built_musl.rs index 2b16b9aa091b..897dfc26e8ca 100644 --- a/library/compiler-builtins/libm/crates/libm-test/tests/compare_built_musl.rs +++ b/library/compiler-builtins/libm/crates/libm-test/tests/compare_built_musl.rs @@ -21,7 +21,7 @@ fn musl_runner( ) { for input in cases { let musl_res = input.call(musl_fn); - let crate_res = input.call(Op::ROUTINE); + let crate_res = input.call_intercept_panics(Op::ROUTINE); crate_res.validate(musl_res, input, ctx).unwrap(); } diff --git a/library/compiler-builtins/libm/crates/libm-test/tests/multiprecision.rs b/library/compiler-builtins/libm/crates/libm-test/tests/multiprecision.rs index fd1f11610f52..0ab4b64da814 100644 --- a/library/compiler-builtins/libm/crates/libm-test/tests/multiprecision.rs +++ b/library/compiler-builtins/libm/crates/libm-test/tests/multiprecision.rs @@ -12,7 +12,7 @@ fn mp_runner(ctx: &CheckCtx, cases: impl Iterator( cases: impl Iterator, ) { for (input, expected) in cases { - let crate_res = input.call(Op::ROUTINE); + let crate_res = input.call_intercept_panics(Op::ROUTINE); crate_res.validate(expected, input, ctx).unwrap(); } } diff --git a/library/compiler-builtins/libm/crates/libm-test/tests/z_extensive/run.rs b/library/compiler-builtins/libm/crates/libm-test/tests/z_extensive/run.rs index a323c9110ee8..786546a9d6d5 100644 --- a/library/compiler-builtins/libm/crates/libm-test/tests/z_extensive/run.rs +++ b/library/compiler-builtins/libm/crates/libm-test/tests/z_extensive/run.rs @@ -113,7 +113,7 @@ where for input in input_vec { // Test the input. let mp_res = Op::run(mp_vals, input); - let crate_res = input.call(Op::ROUTINE); + let crate_res = input.call_intercept_panics(Op::ROUTINE); crate_res.validate(mp_res, input, ctx)?; let completed = completed.fetch_add(1, Ordering::Relaxed) + 1; diff --git a/library/compiler-builtins/libm/crates/util/src/main.rs b/library/compiler-builtins/libm/crates/util/src/main.rs index 130ac45319be..ef70ec9035b8 100644 --- a/library/compiler-builtins/libm/crates/util/src/main.rs +++ b/library/compiler-builtins/libm/crates/util/src/main.rs @@ -59,7 +59,7 @@ macro_rules! handle_call { let libm_fn: ::RustFn = libm::$fn_name; let output = match $basis { - "libm" => input.call(libm_fn), + "libm" => input.call_intercept_panics(libm_fn), #[cfg(feature = "build-musl")] "musl" => { let musl_fn: ::CFn =