Skip to content

Missed-optimization: extern "C" fn type calls are not nounwind #64090

Open
@gnzlbg

Description

@gnzlbg

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

No one assigned

    Labels

    A-FFIArea: Foreign function interface (FFI)A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchI-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions