Skip to content

Commit b6e4299

Browse files
committed
Auto merge of #121548 - RalfJung:ffi-unwind-intrinsics, r=davidtwco
ffi_unwind_calls: treat RustIntrinsic like regular Rust calls Also add some comments to `abi_can_unwind` to explain what happens. r? `@nbdd0121` Cc `@BatmanAoD`
2 parents 9afdb8d + f5c80dc commit b6e4299

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

compiler/rustc_mir_transform/src/ffi_unwind_calls.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ use rustc_target::spec::PanicStrategy;
1010

1111
use crate::errors;
1212

13+
/// Some of the functions declared as "may unwind" by `fn_can_unwind` can't actually unwind. In
14+
/// particular, `extern "C"` is still considered as can-unwind on stable, but we need to to consider
15+
/// it cannot-unwind here. So below we check `fn_can_unwind() && abi_can_unwind()` before concluding
16+
/// that a function call can unwind.
1317
fn abi_can_unwind(abi: Abi) -> bool {
1418
use Abi::*;
1519
match abi {
@@ -33,9 +37,8 @@ fn abi_can_unwind(abi: Abi) -> bool {
3337
| RiscvInterruptS
3438
| CCmseNonSecureCall
3539
| Wasm
36-
| RustIntrinsic
3740
| Unadjusted => false,
38-
Rust | RustCall | RustCold => true,
41+
RustIntrinsic | Rust | RustCall | RustCold => unreachable!(), // these ABIs are already skipped earlier
3942
}
4043
}
4144

@@ -81,14 +84,16 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
8184
let sig = ty.fn_sig(tcx);
8285

8386
// Rust calls cannot themselves create foreign unwinds.
84-
if let Abi::Rust | Abi::RustCall | Abi::RustCold = sig.abi() {
87+
// We assume this is true for intrinsics as well.
88+
if let Abi::RustIntrinsic | Abi::Rust | Abi::RustCall | Abi::RustCold = sig.abi() {
8589
continue;
8690
};
8791

8892
let fn_def_id = match ty.kind() {
8993
ty::FnPtr(_) => None,
9094
&ty::FnDef(def_id, _) => {
91-
// Rust calls cannot themselves create foreign unwinds.
95+
// Rust calls cannot themselves create foreign unwinds (even if they use a non-Rust ABI).
96+
// So the leak of the foreign unwind into Rust can only be elsewhere, not here.
9297
if !tcx.is_foreign_item(def_id) {
9398
continue;
9499
}

library/core/src/intrinsics.rs

+10
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@
4444
//! * Sequentially consistent - sequentially consistent operations are
4545
//! guaranteed to happen in order. This is the standard mode for working
4646
//! with atomic types and is equivalent to Java's `volatile`.
47+
//!
48+
//! # Unwinding
49+
//!
50+
//! Rust intrinsics may, in general, unwind. If an intrinsic can never unwind, add the
51+
//! `#[rustc_nounwind]` attribute so that the compiler can make use of this fact.
52+
//!
53+
//! However, even for intrinsics that may unwind, rustc assumes that a Rust intrinsics will never
54+
//! initiate a foreign (non-Rust) unwind, and thus for panic=abort we can always assume that these
55+
//! intrinsics cannot unwind.
4756
4857
#![unstable(
4958
feature = "core_intrinsics",
@@ -692,6 +701,7 @@ extern "rust-intrinsic" {
692701
/// The stabilized version of this intrinsic is available on the
693702
/// [`atomic`] signed integer types via the `fetch_min` method by passing
694703
/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_min`].
704+
#[rustc_nounwind]
695705
pub fn atomic_min_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
696706
/// Minimum with the current value using a signed comparison.
697707
///

0 commit comments

Comments
 (0)