Skip to content

ffi_unwind_calls: treat RustIntrinsic like regular Rust calls #121548

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ use rustc_target::spec::PanicStrategy;

use crate::errors;

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

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

// Rust calls cannot themselves create foreign unwinds.
if let Abi::Rust | Abi::RustCall | Abi::RustCold = sig.abi() {
// We assume this is true for intrinsics as well.
if let Abi::RustIntrinsic | Abi::Rust | Abi::RustCall | Abi::RustCold = sig.abi() {
continue;
};

let fn_def_id = match ty.kind() {
ty::FnPtr(_) => None,
&ty::FnDef(def_id, _) => {
// Rust calls cannot themselves create foreign unwinds.
// Rust calls cannot themselves create foreign unwinds (even if they use a non-Rust ABI).
// So the leak of the foreign unwind into Rust can only be elsewhere, not here.
if !tcx.is_foreign_item(def_id) {
continue;
}
Expand Down
10 changes: 10 additions & 0 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@
//! * Sequentially consistent - sequentially consistent operations are
//! guaranteed to happen in order. This is the standard mode for working
//! with atomic types and is equivalent to Java's `volatile`.
//!
//! # Unwinding
//!
//! Rust intrinsics may, in general, unwind. If an intrinsic can never unwind, add the
//! `#[rustc_nounwind]` attribute so that the compiler can make use of this fact.
//!
//! However, even for intrinsics that may unwind, rustc assumes that a Rust intrinsics will never
//! initiate a foreign (non-Rust) unwind, and thus for panic=abort we can always assume that these
//! intrinsics cannot unwind.

#![unstable(
feature = "core_intrinsics",
Expand Down Expand Up @@ -692,6 +701,7 @@ extern "rust-intrinsic" {
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] signed integer types via the `fetch_min` method by passing
/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_min`].
#[rustc_nounwind]
pub fn atomic_min_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
/// Minimum with the current value using a signed comparison.
///
Expand Down