Skip to content

Commit

Permalink
Auto merge of #121548 - RalfJung:ffi-unwind-intrinsics, r=davidtwco
Browse files Browse the repository at this point in the history
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`
  • Loading branch information
bors committed Feb 27, 2024
2 parents 9afdb8d + f5c80dc commit b6e4299
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
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

0 comments on commit b6e4299

Please sign in to comment.