rename 'try' intrinsic to 'catch_unwind'

This commit is contained in:
Ralf Jung 2024-02-25 18:51:22 +01:00
parent e9f9594913
commit b4ca582b89
16 changed files with 42 additions and 30 deletions

View File

@ -23,7 +23,7 @@ use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::GenericArgsRef;
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::symbol::{sym, Symbol};
pub(crate) use self::llvm::codegen_llvm_intrinsic_call; pub(crate) use self::llvm::codegen_llvm_intrinsic_call;
use crate::prelude::*; use crate::prelude::*;
@ -1132,7 +1132,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
ret.write_cvalue(fx, val); ret.write_cvalue(fx, val);
} }
kw::Try => { sym::catch_unwind => {
intrinsic_args!(fx, args => (f, data, catch_fn); intrinsic); intrinsic_args!(fx, args => (f, data, catch_fn); intrinsic);
let f = f.load_scalar(fx); let f = f.load_scalar(fx);
let data = data.load_scalar(fx); let data = data.load_scalar(fx);

View File

@ -21,7 +21,7 @@ use rustc_middle::ty::{self, Instance, Ty};
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
#[cfg(feature="master")] #[cfg(feature="master")]
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
use rustc_span::{Span, Symbol, symbol::kw, sym}; use rustc_span::{Span, Symbol, sym};
use rustc_target::abi::HasDataLayout; use rustc_target::abi::HasDataLayout;
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
use rustc_target::spec::PanicStrategy; use rustc_target::spec::PanicStrategy;
@ -129,7 +129,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
let res = self.context.new_call(None, builtin, &[a]); let res = self.context.new_call(None, builtin, &[a]);
self.icmp(IntPredicate::IntEQ, res, self.const_i32(0)) self.icmp(IntPredicate::IntEQ, res, self.const_i32(0))
} }
kw::Try => { sym::catch_unwind => {
try_intrinsic( try_intrinsic(
self, self,
args[0].immediate(), args[0].immediate(),

View File

@ -17,7 +17,7 @@ use rustc_hir as hir;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::ty::{self, GenericArgsRef, Ty};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::{sym, symbol::kw, Span, Symbol}; use rustc_span::{sym, Span, Symbol};
use rustc_target::abi::{self, Align, HasDataLayout, Primitive}; use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use rustc_target::spec::{HasTargetSpec, PanicStrategy};
@ -133,8 +133,8 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
} }
sym::unlikely => self sym::unlikely => self
.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]), .call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]),
kw::Try => { sym::catch_unwind => {
try_intrinsic( catch_unwind_intrinsic(
self, self,
args[0].immediate(), args[0].immediate(),
args[1].immediate(), args[1].immediate(),
@ -457,7 +457,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
} }
} }
fn try_intrinsic<'ll>( fn catch_unwind_intrinsic<'ll>(
bx: &mut Builder<'_, 'll, '_>, bx: &mut Builder<'_, 'll, '_>,
try_func: &'ll Value, try_func: &'ll Value,
data: &'ll Value, data: &'ll Value,

View File

@ -12,7 +12,7 @@ use rustc_hir as hir;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{kw, sym}; use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
@ -445,7 +445,7 @@ pub fn check_intrinsic_type(
) )
} }
kw::Try => { sym::catch_unwind => {
let mut_u8 = Ty::new_mut_ptr(tcx, tcx.types.u8); let mut_u8 = Ty::new_mut_ptr(tcx, tcx.types.u8);
let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig( let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
[mut_u8], [mut_u8],

View File

@ -487,6 +487,7 @@ symbols! {
call_once, call_once,
caller_location, caller_location,
capture_disjoint_fields, capture_disjoint_fields,
catch_unwind,
cause, cause,
cdylib, cdylib,
ceilf32, ceilf32,

View File

@ -75,6 +75,9 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
unsafe { crate::ptr::drop_in_place(to_drop) } unsafe { crate::ptr::drop_in_place(to_drop) }
} }
#[cfg(bootstrap)]
pub use self::r#try as catch_unwind;
extern "rust-intrinsic" { extern "rust-intrinsic" {
// N.B., these intrinsics take raw pointers because they mutate aliased // N.B., these intrinsics take raw pointers because they mutate aliased
// memory, which is not valid for either `&` or `&mut`. // memory, which is not valid for either `&` or `&mut`.
@ -2382,16 +2385,24 @@ extern "rust-intrinsic" {
#[rustc_nounwind] #[rustc_nounwind]
pub fn variant_count<T>() -> usize; pub fn variant_count<T>() -> usize;
/// Rust's "try catch" construct which invokes the function pointer `try_fn` /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the
/// with the data pointer `data`. /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs.
///
/// The third argument is a function called if a panic occurs. This function
/// takes the data pointer and a pointer to the target-specific exception
/// object that was caught. For more information see the compiler's
/// source as well as std's catch implementation.
/// ///
/// `catch_fn` must not unwind. /// `catch_fn` must not unwind.
///
/// The third argument is a function called if an unwind occurs (both Rust unwinds and foreign
/// unwinds). This function takes the data pointer and a pointer to the target-specific
/// exception object that was caught. For more information, see the compiler's source as well as
/// std's `catch_unwind` implementation.
///
/// The stable version of this intrinsic is `std::panic::catch_unwind`.
#[rustc_nounwind] #[rustc_nounwind]
#[cfg(not(bootstrap))]
pub fn catch_unwind(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32;
/// For bootstrap only, see `catch_unwind`.
#[rustc_nounwind]
#[cfg(bootstrap)]
pub fn r#try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32; pub fn r#try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32;
/// Emits a `!nontemporal` store according to LLVM (see their docs). /// Emits a `!nontemporal` store according to LLVM (see their docs).

View File

@ -508,12 +508,12 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
// Access to the union's fields: this is `std` and we know that the `r#try` // Access to the union's fields: this is `std` and we know that the `r#try`
// intrinsic fills in the `r` or `p` union field based on its return value. // intrinsic fills in the `r` or `p` union field based on its return value.
// //
// The call to `intrinsics::r#try` is made safe by: // The call to `intrinsics::catch_unwind` is made safe by:
// - `do_call`, the first argument, can be called with the initial `data_ptr`. // - `do_call`, the first argument, can be called with the initial `data_ptr`.
// - `do_catch`, the second argument, can be called with the `data_ptr` as well. // - `do_catch`, the second argument, can be called with the `data_ptr` as well.
// See their safety preconditions for more information // See their safety preconditions for more information
unsafe { unsafe {
return if intrinsics::r#try(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 { return if intrinsics::catch_unwind(do_call::<F, R>, data_ptr, do_catch::<F, R>) == 0 {
Ok(ManuallyDrop::into_inner(data.r)) Ok(ManuallyDrop::into_inner(data.r))
} else { } else {
Err(ManuallyDrop::into_inner(data.p)) Err(ManuallyDrop::into_inner(data.p))
@ -540,7 +540,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
// Its must contains a valid `f` (type: F) value that can be use to fill // Its must contains a valid `f` (type: F) value that can be use to fill
// `data.r`. // `data.r`.
// //
// This function cannot be marked as `unsafe` because `intrinsics::r#try` // This function cannot be marked as `unsafe` because `intrinsics::catch_unwind`
// expects normal function pointers. // expects normal function pointers.
#[inline] #[inline]
fn do_call<F: FnOnce() -> R, R>(data: *mut u8) { fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
@ -562,7 +562,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
// Since this uses `cleanup` it also hinges on a correct implementation of // Since this uses `cleanup` it also hinges on a correct implementation of
// `__rustc_panic_cleanup`. // `__rustc_panic_cleanup`.
// //
// This function cannot be marked as `unsafe` because `intrinsics::r#try` // This function cannot be marked as `unsafe` because `intrinsics::catch_unwind`
// expects normal function pointers. // expects normal function pointers.
#[inline] #[inline]
#[rustc_nounwind] // `intrinsic::r#try` requires catch fn to be nounwind #[rustc_nounwind] // `intrinsic::r#try` requires catch fn to be nounwind

View File

@ -54,7 +54,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// Some intrinsics are special and need the "ret". // Some intrinsics are special and need the "ret".
match intrinsic_name { match intrinsic_name {
"try" => return this.handle_try(args, dest, ret), "catch_unwind" => return this.handle_catch_unwind(args, dest, ret),
_ => {} _ => {}
} }

View File

@ -69,7 +69,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
} }
/// Handles the `try` intrinsic, the underlying implementation of `std::panicking::try`. /// Handles the `try` intrinsic, the underlying implementation of `std::panicking::try`.
fn handle_try( fn handle_catch_unwind(
&mut self, &mut self,
args: &[OpTy<'tcx, Provenance>], args: &[OpTy<'tcx, Provenance>],
dest: &PlaceTy<'tcx, Provenance>, dest: &PlaceTy<'tcx, Provenance>,

View File

@ -8,7 +8,7 @@ fn main() {
unsafe { unsafe {
// Make sure we check the ABI when Miri itself invokes a function // Make sure we check the ABI when Miri itself invokes a function
// as part of a shim implementation. // as part of a shim implementation.
std::intrinsics::r#try( std::intrinsics::catch_unwind(
//~^ ERROR: calling a function with ABI C using caller ABI Rust //~^ ERROR: calling a function with ABI C using caller ABI Rust
std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn), std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
std::ptr::null_mut(), std::ptr::null_mut(),

View File

@ -1,7 +1,7 @@
error: Undefined Behavior: calling a function with ABI C using caller ABI Rust error: Undefined Behavior: calling a function with ABI C using caller ABI Rust
--> $DIR/check_callback_abi.rs:LL:CC --> $DIR/check_callback_abi.rs:LL:CC
| |
LL | / std::intrinsics::r#try( LL | / std::intrinsics::catch_unwind(
LL | | LL | |
LL | | std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn), LL | | std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
LL | | std::ptr::null_mut(), LL | | std::ptr::null_mut(),

View File

@ -15,7 +15,7 @@ fn main() {
unsafe { unsafe {
let _ = malloc(0); let _ = malloc(0);
std::mem::transmute::<fn(), extern "C" fn()>(foo)(); std::mem::transmute::<fn(), extern "C" fn()>(foo)();
std::intrinsics::r#try( std::intrinsics::catch_unwind(
std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn), std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
std::ptr::null_mut(), std::ptr::null_mut(),
|_, _| unreachable!(), |_, _| unreachable!(),

View File

@ -41,7 +41,7 @@ pub fn test_cleanup() {
#[no_mangle] #[no_mangle]
pub fn test_rtry() { pub fn test_rtry() {
unsafe { unsafe {
core::intrinsics::r#try(|_| { core::intrinsics::catch_unwind(|_| {
may_panic(); may_panic();
}, core::ptr::null_mut(), |data, exception| { }, core::ptr::null_mut(), |data, exception| {
log_number(data as usize); log_number(data as usize);

View File

@ -35,7 +35,7 @@ pub fn test_cleanup() {
#[no_mangle] #[no_mangle]
pub fn test_rtry() { pub fn test_rtry() {
unsafe { unsafe {
core::intrinsics::r#try(|_| { core::intrinsics::catch_unwind(|_| {
may_panic(); may_panic();
}, core::ptr::null_mut(), |data, exception| { }, core::ptr::null_mut(), |data, exception| {
log_number(data as usize); log_number(data as usize);

View File

@ -39,7 +39,7 @@ pub extern "C" fn start() -> usize {
let data = 0x1234usize as *mut u8; // Something to recognize let data = 0x1234usize as *mut u8; // Something to recognize
unsafe { unsafe {
core::intrinsics::r#try(|data: *mut u8| { core::intrinsics::catch_unwind(|data: *mut u8| {
let _log_on_drop = LogOnDrop; let _log_on_drop = LogOnDrop;
logging::log_str(&alloc::format!("`r#try` called with ptr {:?}", data)); logging::log_str(&alloc::format!("`r#try` called with ptr {:?}", data));

View File

@ -15,7 +15,7 @@ note: required because it's used within this closure
| |
LL | catch_unwind(|| { x.set(23); }); LL | catch_unwind(|| { x.set(23); });
| ^^ | ^^
note: required by a bound in `catch_unwind` note: required by a bound in `std::panic::catch_unwind`
--> $SRC_DIR/std/src/panic.rs:LL:COL --> $SRC_DIR/std/src/panic.rs:LL:COL
error: aborting due to 1 previous error error: aborting due to 1 previous error