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`
This commit is contained in:
commit
b6e4299415
@ -10,6 +10,10 @@ use rustc_target::spec::PanicStrategy;
|
|||||||
|
|
||||||
use crate::errors;
|
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 {
|
fn abi_can_unwind(abi: Abi) -> bool {
|
||||||
use Abi::*;
|
use Abi::*;
|
||||||
match abi {
|
match abi {
|
||||||
@ -33,9 +37,8 @@ fn abi_can_unwind(abi: Abi) -> bool {
|
|||||||
| RiscvInterruptS
|
| RiscvInterruptS
|
||||||
| CCmseNonSecureCall
|
| CCmseNonSecureCall
|
||||||
| Wasm
|
| Wasm
|
||||||
| RustIntrinsic
|
|
||||||
| Unadjusted => false,
|
| Unadjusted => false,
|
||||||
Rust | RustCall | RustCold => true,
|
RustIntrinsic | Rust | RustCall | RustCold => unreachable!(), // these ABIs are already skipped earlier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,14 +84,16 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
|
|||||||
let sig = ty.fn_sig(tcx);
|
let sig = ty.fn_sig(tcx);
|
||||||
|
|
||||||
// Rust calls cannot themselves create foreign unwinds.
|
// 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;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let fn_def_id = match ty.kind() {
|
let fn_def_id = match ty.kind() {
|
||||||
ty::FnPtr(_) => None,
|
ty::FnPtr(_) => None,
|
||||||
&ty::FnDef(def_id, _) => {
|
&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) {
|
if !tcx.is_foreign_item(def_id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,15 @@
|
|||||||
//! * Sequentially consistent - sequentially consistent operations are
|
//! * Sequentially consistent - sequentially consistent operations are
|
||||||
//! guaranteed to happen in order. This is the standard mode for working
|
//! guaranteed to happen in order. This is the standard mode for working
|
||||||
//! with atomic types and is equivalent to Java's `volatile`.
|
//! 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(
|
#![unstable(
|
||||||
feature = "core_intrinsics",
|
feature = "core_intrinsics",
|
||||||
@ -692,6 +701,7 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized version of this intrinsic is available on the
|
/// The stabilized version of this intrinsic is available on the
|
||||||
/// [`atomic`] signed integer types via the `fetch_min` method by passing
|
/// [`atomic`] signed integer types via the `fetch_min` method by passing
|
||||||
/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_min`].
|
/// [`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;
|
pub fn atomic_min_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
|
||||||
/// Minimum with the current value using a signed comparison.
|
/// Minimum with the current value using a signed comparison.
|
||||||
///
|
///
|
||||||
|
Loading…
x
Reference in New Issue
Block a user