From 2fd4dd20d717b3e8af4bdff2873b348920426425 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Thu, 25 Mar 2021 18:49:35 +0800 Subject: [PATCH] Allow using `-C force-unwind-tables=no` when `panic=unwind` --- compiler/rustc_session/src/session.rs | 25 +++++--------- .../assembly/panic-no-unwind-no-uwtable.rs | 8 +++++ src/test/assembly/panic-unwind-no-uwtable.rs | 12 +++++++ src/test/codegen/force-no-unwind-tables.rs | 6 +++- .../codegen/panic-unwind-default-uwtable.rs | 6 ++++ .../unwind-tables-panic-required.rs | 10 ------ src/test/ui/unwind-no-uwtable.rs | 34 +++++++++++++++++++ 7 files changed, 74 insertions(+), 27 deletions(-) create mode 100644 src/test/assembly/panic-no-unwind-no-uwtable.rs create mode 100644 src/test/assembly/panic-unwind-no-uwtable.rs create mode 100644 src/test/codegen/panic-unwind-default-uwtable.rs delete mode 100644 src/test/ui/panic-runtime/unwind-tables-panic-required.rs create mode 100644 src/test/ui/unwind-no-uwtable.rs diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 3488efacd1126..cc2583be94474 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -807,8 +807,11 @@ impl Session { // This is used to control the emission of the `uwtable` attribute on // LLVM functions. // - // At the very least, unwind tables are needed when compiling with - // `-C panic=unwind`. + // Unwind tables are needed when compiling with `-C panic=unwind`, but + // LLVM won't omit unwind tables unless the function is also marked as + // `nounwind`, so users are allowed to disable `uwtable` emission. + // Historically rustc always emits `uwtable` attributes by default, so + // even they can be disabled, they're still emitted by default. // // On some targets (including windows), however, exceptions include // other events such as illegal instructions, segfaults, etc. This means @@ -821,13 +824,10 @@ impl Session { // If a target requires unwind tables, then they must be emitted. // Otherwise, we can defer to the `-C force-unwind-tables=` // value, if it is provided, or disable them, if not. - if self.panic_strategy() == PanicStrategy::Unwind { - true - } else if self.target.requires_uwtable { - true - } else { - self.opts.cg.force_unwind_tables.unwrap_or(self.target.default_uwtable) - } + self.target.requires_uwtable + || self.opts.cg.force_unwind_tables.unwrap_or( + self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable, + ) } /// Returns the symbol name for the registrar function, @@ -1483,13 +1483,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // Unwind tables cannot be disabled if the target requires them. if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables { - if sess.panic_strategy() == PanicStrategy::Unwind && !include_uwtables { - sess.err( - "panic=unwind requires unwind tables, they cannot be disabled \ - with `-C force-unwind-tables=no`.", - ); - } - if sess.target.requires_uwtable && !include_uwtables { sess.err( "target requires unwind tables, they cannot be disabled with \ diff --git a/src/test/assembly/panic-no-unwind-no-uwtable.rs b/src/test/assembly/panic-no-unwind-no-uwtable.rs new file mode 100644 index 0000000000000..499d4e6986717 --- /dev/null +++ b/src/test/assembly/panic-no-unwind-no-uwtable.rs @@ -0,0 +1,8 @@ +// assembly-output: emit-asm +// only-x86_64-unknown-linux-gnu +// compile-flags: -C panic=unwind -C force-unwind-tables=n -O + +#![crate_type = "lib"] + +// CHECK-NOT: .cfi_startproc +pub fn foo() {} diff --git a/src/test/assembly/panic-unwind-no-uwtable.rs b/src/test/assembly/panic-unwind-no-uwtable.rs new file mode 100644 index 0000000000000..8eed72b2fca69 --- /dev/null +++ b/src/test/assembly/panic-unwind-no-uwtable.rs @@ -0,0 +1,12 @@ +// assembly-output: emit-asm +// only-x86_64-unknown-linux-gnu +// compile-flags: -C panic=unwind -C force-unwind-tables=n + +#![crate_type = "lib"] + +// CHECK-LABEL: foo: +// CHECK: .cfi_startproc +#[no_mangle] +fn foo() { + panic!(); +} diff --git a/src/test/codegen/force-no-unwind-tables.rs b/src/test/codegen/force-no-unwind-tables.rs index dc77e6cb70917..3ee23f05eb2b1 100644 --- a/src/test/codegen/force-no-unwind-tables.rs +++ b/src/test/codegen/force-no-unwind-tables.rs @@ -3,5 +3,9 @@ #![crate_type="lib"] +// CHECK-LABEL: define{{.*}}void @foo // CHECK-NOT: attributes #{{.*}} uwtable -pub fn foo() {} +#[no_mangle] +fn foo() { + panic!(); +} diff --git a/src/test/codegen/panic-unwind-default-uwtable.rs b/src/test/codegen/panic-unwind-default-uwtable.rs new file mode 100644 index 0000000000000..4c85008cf359a --- /dev/null +++ b/src/test/codegen/panic-unwind-default-uwtable.rs @@ -0,0 +1,6 @@ +// compile-flags: -C panic=unwind -C no-prepopulate-passes + +#![crate_type = "lib"] + +// CHECK: attributes #{{.*}} uwtable +pub fn foo() {} diff --git a/src/test/ui/panic-runtime/unwind-tables-panic-required.rs b/src/test/ui/panic-runtime/unwind-tables-panic-required.rs deleted file mode 100644 index 79e91879051c8..0000000000000 --- a/src/test/ui/panic-runtime/unwind-tables-panic-required.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Tests that the compiler errors if the user tries to turn off unwind tables -// when they are required. -// -// dont-check-compiler-stderr -// compile-flags: -C panic=unwind -C force-unwind-tables=no -// -// error-pattern: panic=unwind requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`. - -pub fn main() { -} diff --git a/src/test/ui/unwind-no-uwtable.rs b/src/test/ui/unwind-no-uwtable.rs new file mode 100644 index 0000000000000..f249d3f457474 --- /dev/null +++ b/src/test/ui/unwind-no-uwtable.rs @@ -0,0 +1,34 @@ +// run-pass +// ignore-windows target requires uwtable +// ignore-wasm32-bare no proper panic=unwind support +// compile-flags: -C panic=unwind -C force-unwind-tables=n + +use std::panic::{self, AssertUnwindSafe}; + +struct Increase<'a>(&'a mut u8); + +impl Drop for Increase<'_> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +#[inline(never)] +fn unwind() { + panic!(); +} + +#[inline(never)] +fn increase(count: &mut u8) { + let _increase = Increase(count); + unwind(); +} + +fn main() { + let mut count = 0; + assert!(panic::catch_unwind(AssertUnwindSafe( + #[inline(never)] + || increase(&mut count) + )).is_err()); + assert_eq!(count, 1); +}