Auto merge of #144225 - purplesyringa:unwinding-intrinsics, r=nikic
Don't special-case llvm.* as nounwind Certain LLVM intrinsics, such as `llvm.wasm.throw`, can unwind. Marking them as nounwind causes us to skip cleanup of locals and optimize out `catch_unwind` under inlining or when `llvm.wasm.throw` is used directly by user code. The motivation for forcibly marking llvm.* as nounwind is no longer present: most intrinsics are linked as `extern "C"` or other non-unwinding ABIs, so we won't codegen `invoke` for them anyway. Closes rust-lang/rust#132416. `@rustbot` label +T-compiler +A-panic
This commit is contained in:
@@ -511,15 +511,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any linkage to LLVM intrinsics for now forcibly marks them all as never
|
|
||||||
// unwinds since LLVM sometimes can't handle codegen which `invoke`s
|
|
||||||
// intrinsic functions.
|
|
||||||
if let Some(name) = &codegen_fn_attrs.link_name
|
|
||||||
&& name.as_str().starts_with("llvm.")
|
|
||||||
{
|
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(features) = check_tied_features(
|
if let Some(features) = check_tied_features(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
&codegen_fn_attrs
|
&codegen_fn_attrs
|
||||||
|
|||||||
@@ -191,6 +191,16 @@ unsafe extern "C-unwind" {
|
|||||||
// #[cfg_attr(test, assert_instr(throw, TAG = 0, ptr = core::ptr::null_mut()))]
|
// #[cfg_attr(test, assert_instr(throw, TAG = 0, ptr = core::ptr::null_mut()))]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "wasm_exception_handling_intrinsics", issue = "122465")]
|
#[unstable(feature = "wasm_exception_handling_intrinsics", issue = "122465")]
|
||||||
|
// FIXME: Since this instruction unwinds, `core` built with `-C panic=unwind`
|
||||||
|
// cannot be linked with `-C panic=abort` programs. But that's not
|
||||||
|
// entirely supported anyway, because runtimes without EH support won't
|
||||||
|
// be able to handle `try` blocks in `-C panic=unwind` crates either.
|
||||||
|
// We ship `-C panic=abort` `core`, so this doesn't affect users
|
||||||
|
// directly. Resolving this will likely require patching out both `try`
|
||||||
|
// and `throw` instructions, at which point we can look into whitelisting
|
||||||
|
// this function in the compiler to allow linking.
|
||||||
|
// See https://github.com/rust-lang/rust/issues/118168.
|
||||||
|
#[allow(ffi_unwind_calls)]
|
||||||
pub unsafe fn throw<const TAG: i32>(ptr: *mut u8) -> ! {
|
pub unsafe fn throw<const TAG: i32>(ptr: *mut u8) -> ! {
|
||||||
static_assert!(TAG == 0); // LLVM only supports tag 0 == C++ right now.
|
static_assert!(TAG == 0); // LLVM only supports tag 0 == C++ right now.
|
||||||
wasm_throw(TAG, ptr)
|
wasm_throw(TAG, ptr)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//@ compile-flags: -C panic=unwind -Z emscripten-wasm-eh
|
//@ compile-flags: -C panic=unwind -Z emscripten-wasm-eh
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics, wasm_exception_handling_intrinsics)]
|
||||||
|
|
||||||
extern "C-unwind" {
|
extern "C-unwind" {
|
||||||
fn may_panic();
|
fn may_panic();
|
||||||
@@ -57,3 +57,17 @@ pub fn test_rtry() {
|
|||||||
// CHECK: {{.*}} = catchpad within {{.*}} [ptr null]
|
// CHECK: {{.*}} = catchpad within {{.*}} [ptr null]
|
||||||
// CHECK: catchret
|
// CHECK: catchret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure the intrinsic is not inferred as nounwind. This is a regression test for #132416.
|
||||||
|
// CHECK-LABEL: @test_intrinsic() {{.*}} @__gxx_wasm_personality_v0
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn test_intrinsic() {
|
||||||
|
let _log_on_drop = LogOnDrop;
|
||||||
|
unsafe {
|
||||||
|
core::arch::wasm32::throw::<0>(core::ptr::null_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-NOT: call
|
||||||
|
// CHECK: invoke void @llvm.wasm.throw(i32 noundef 0, ptr noundef null)
|
||||||
|
// CHECK: %cleanuppad = cleanuppad within none []
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user