Open
Description
See https://rust.godbolt.org/z/9UvEyu
#![feature(unwind_attributes)]
extern "C" {
#[unwind(allow)] fn foo();
// fn bar();
static bar: extern "C" fn();
static mut BAR: i32;
}
struct Foo;
impl Drop for Foo {
fn drop(&mut self) {
unsafe { BAR = 42; }
}
}
pub unsafe fn unwind() {
let x = Foo;
foo();
std::mem::forget(x);
}
pub unsafe fn nounwind() {
let x = Foo;
bar();
std::mem::forget(x);
}
When the function extern "C" { fn bar(); }
is called, the nounwind
function is compiled to:
example::nounwind:
jmpq *bar@GOTPCREL(%rip)
However, when the function type static bar: extern "C" fn();
is called, this sub-optimal machine code is emitted:
example::nounwind:
pushq %rbx
movq bar@GOTPCREL(%rip), %rax
callq *(%rax)
popq %rbx
retq
movq %rax, %rbx
callq core::ptr::real_drop_in_place
movq %rbx, %rdi
callq _Unwind_Resume@PLT
ud2
This means that we can't call the large majority of C FFI functions, which cannot unwind, and all of the C++ noexcept
functions, which cannot unwind either, from Rust function pointers efficiently.
Metadata
Metadata
Assignees
Labels
Area: Foreign function interface (FFI)Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Category: An issue highlighting optimization opportunities or PRs implementing suchIssue: Problems and improvements with respect to performance of generated code.Relevant to the compiler team, which will review and decide on the PR/issue.Relevant to the language team, which will review and decide on the PR/issue.