Skip to content

Make rust-intrinsic ABI unwindable #110233

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 4 commits into from
Apr 13, 2023
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
5 changes: 3 additions & 2 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1226,10 +1226,11 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
| AvrNonBlockingInterrupt
| CCmseNonSecureCall
| Wasm
| RustIntrinsic
| PlatformIntrinsic
| Unadjusted => false,
Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind,
Rust | RustCall | RustCold | RustIntrinsic => {
tcx.sess.panic_strategy() == PanicStrategy::Unwind
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions library/core/src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,12 +615,15 @@ impl<'f> Drop for VaListImpl<'f> {
extern "rust-intrinsic" {
/// Destroy the arglist `ap` after initialization with `va_start` or
/// `va_copy`.
#[rustc_nounwind]
fn va_end(ap: &mut VaListImpl<'_>);

/// Copies the current location of arglist `src` to the arglist `dst`.
#[rustc_nounwind]
fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>);

/// Loads an argument of type `T` from the `va_list` `ap` and increment the
/// argument `ap` points to.
#[rustc_nounwind]
fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
}
232 changes: 231 additions & 1 deletion library/core/src/intrinsics.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,7 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
// as `intrinsics::copy_nonoverlapping` is a wrapper function.
extern "rust-intrinsic" {
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
#[rustc_nounwind]
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
}

Expand Down
1 change: 1 addition & 0 deletions library/std/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
// This function cannot be marked as `unsafe` because `intrinsics::r#try`
// expects normal function pointers.
#[inline]
#[rustc_nounwind] // `intrinsic::r#try` requires catch fn to be nounwind
fn do_catch<F: FnOnce() -> R, R>(data: *mut u8, payload: *mut u8) {
// SAFETY: this is the responsibility of the caller, see above.
//
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// MIR for `main` after AbortUnwindingCalls

fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/issue_104451_unwindable_intrinsics.rs:+0:11: +0:11
let mut _1: !; // in scope 0 at $DIR/issue_104451_unwindable_intrinsics.rs:+2:9: +2:62
let mut _2: (); // in scope 0 at $DIR/issue_104451_unwindable_intrinsics.rs:+2:45: +2:47
scope 1 {
}

bb0: {
StorageLive(_1); // scope 1 at $DIR/issue_104451_unwindable_intrinsics.rs:+2:9: +2:62
StorageLive(_2); // scope 1 at $DIR/issue_104451_unwindable_intrinsics.rs:+2:45: +2:47
_2 = (); // scope 1 at $DIR/issue_104451_unwindable_intrinsics.rs:+2:45: +2:47
_1 = const_eval_select::<(), fn() -> ! {ow_ct}, fn() -> ! {ow_ct}, !>(move _2, ow_ct, ow_ct); // scope 1 at $DIR/issue_104451_unwindable_intrinsics.rs:+2:9: +2:62
// mir::Constant
// + span: $DIR/issue_104451_unwindable_intrinsics.rs:8:9: 8:44
// + literal: Const { ty: unsafe extern "rust-intrinsic" fn((), fn() -> ! {ow_ct}, fn() -> ! {ow_ct}) -> ! {const_eval_select::<(), fn() -> ! {ow_ct}, fn() -> ! {ow_ct}, !>}, val: Value(<ZST>) }
// mir::Constant
// + span: $DIR/issue_104451_unwindable_intrinsics.rs:8:49: 8:54
// + literal: Const { ty: fn() -> ! {ow_ct}, val: Value(<ZST>) }
// mir::Constant
// + span: $DIR/issue_104451_unwindable_intrinsics.rs:8:56: 8:61
// + literal: Const { ty: fn() -> ! {ow_ct}, val: Value(<ZST>) }
}
}
14 changes: 14 additions & 0 deletions tests/mir-opt/issue_104451_unwindable_intrinsics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Check that `UnwindAction::Unreachable` is not generated for unwindable intrinsics.
// ignore-wasm32 compiled with panic=abort by default
#![feature(core_intrinsics)]

// EMIT_MIR issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.mir
fn main() {
unsafe {
core::intrinsics::const_eval_select((), ow_ct, ow_ct)
}
}

const fn ow_ct() -> ! {
panic!();
}
2 changes: 1 addition & 1 deletion tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
StorageLive(_1); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
- _1 = std::intrinsics::assume(const true) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:105:9: 105:32
- // + span: $DIR/lower_intrinsics.rs:106:9: 106:32
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(bool) {std::intrinsics::assume}, val: Value(<ZST>) }
+ assume(const true); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
+ goto -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
StorageDead(_9); // scope 3 at $DIR/lower_intrinsics.rs:+4:90: +4:91
- _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> [return: bb1, unwind unreachable]; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:98:9: 98:28
- // + span: $DIR/lower_intrinsics.rs:99:9: 99:28
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32, *mut i32, usize) {copy_nonoverlapping::<i32>}, val: Value(<ZST>) }
+ copy_nonoverlapping(dst = move _8, src = move _4, count = const 0_usize); // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
+ goto -> bb1; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
_4 = &raw const (*_1); // scope 1 at $DIR/lower_intrinsics.rs:+2:55: +2:56
- _3 = option_payload_ptr::<usize>(move _4) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:132:18: 132:54
- // + span: $DIR/lower_intrinsics.rs:133:18: 133:54
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Option<usize>) -> *const usize {option_payload_ptr::<usize>}, val: Value(<ZST>) }
+ _3 = &raw const (((*_4) as Some).0: usize); // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57
+ goto -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57
Expand All @@ -37,7 +37,7 @@
_6 = &raw const (*_2); // scope 2 at $DIR/lower_intrinsics.rs:+3:55: +3:56
- _5 = option_payload_ptr::<String>(move _6) -> [return: bb2, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:133:18: 133:54
- // + span: $DIR/lower_intrinsics.rs:134:18: 134:54
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Option<String>) -> *const String {option_payload_ptr::<String>}, val: Value(<ZST>) }
+ _5 = &raw const (((*_6) as Some).0: std::string::String); // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57
+ goto -> bb2; // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
_2 = &raw const (*_1); // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
- _0 = read_via_copy::<i32>(move _2) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:118:14: 118:45
- // + span: $DIR/lower_intrinsics.rs:119:14: 119:45
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32) -> i32 {read_via_copy::<i32>}, val: Value(<ZST>) }
+ _0 = (*_2); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
+ goto -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
_2 = &raw const (*_1); // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
- _0 = read_via_copy::<Never>(move _2) -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:123:14: 123:45
- // + span: $DIR/lower_intrinsics.rs:124:14: 124:45
- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Never) -> Never {read_via_copy::<Never>}, val: Value(<ZST>) }
+ unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
}
Expand Down
3 changes: 2 additions & 1 deletion tests/mir-opt/lower_intrinsics.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// unit-test: LowerIntrinsics
// ignore-wasm32 compiled with panic=abort by default

#![feature(core_intrinsics, intrinsics)]
#![feature(core_intrinsics, intrinsics, rustc_attrs)]
#![crate_type = "lib"]

// EMIT_MIR lower_intrinsics.wrapping.LowerIntrinsics.diff
Expand Down Expand Up @@ -87,6 +87,7 @@ pub fn discriminant<T>(t: T) {

extern "rust-intrinsic" {
// Cannot use `std::intrinsics::copy_nonoverlapping` as that is a wrapper function
#[rustc_nounwind]
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
_5 = _2; // scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54
- _3 = add_with_overflow::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:111:14: 111:49
- // + span: $DIR/lower_intrinsics.rs:112:14: 112:49
- // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {add_with_overflow::<i32>}, val: Value(<ZST>) }
+ _3 = CheckedAdd(move _4, move _5); // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
Expand All @@ -48,7 +48,7 @@
_8 = _2; // scope 1 at $DIR/lower_intrinsics.rs:+2:53: +2:54
- _6 = sub_with_overflow::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:112:14: 112:49
- // + span: $DIR/lower_intrinsics.rs:113:14: 113:49
- // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {sub_with_overflow::<i32>}, val: Value(<ZST>) }
+ _6 = CheckedSub(move _7, move _8); // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
+ goto -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
Expand All @@ -64,7 +64,7 @@
_11 = _2; // scope 2 at $DIR/lower_intrinsics.rs:+3:53: +3:54
- _9 = mul_with_overflow::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:113:14: 113:49
- // + span: $DIR/lower_intrinsics.rs:114:14: 114:49
- // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {mul_with_overflow::<i32>}, val: Value(<ZST>) }
+ _9 = CheckedMul(move _10, move _11); // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
+ goto -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
Expand Down