Closed
Description
While filling #64222 I noticed that we generate more code than C++ for catch_unwind
. That did not feel right, since C++'s catch
can do much more than Rust's catch unwind, e.g., filtering different types of exceptions, etc.
MWE: C++ (https://gcc.godbolt.org/z/z_dgPg):
extern "C" void foo();
int bar() {
try {
foo();
return 42;
} catch(...) {
return 13;
}
}
generates
bar(): # @bar()
push rbx
mov ebx, 42
call foo
mov eax, ebx
pop rbx
ret
mov rdi, rax
call __cxa_begin_catch
call __cxa_end_catch
mov ebx, 13
mov eax, ebx
pop rbx
ret
while Rust (https://gcc.godbolt.org/z/4sbc6k):
#![feature(unwind_attributes)]
extern "C" {
// can unwind:
#[unwind(allow)] fn foo();
}
pub unsafe fn bar() -> i32 {
std::panic::catch_unwind(|| { foo(); 42 }).unwrap_or(13)
}
generates
example::bar:
push rbp
push r14
push rbx
sub rsp, 32
mov qword ptr [rsp + 16], 0
mov qword ptr [rsp + 24], 0
lea rdi, [rip + std::panicking::try::do_call]
lea rsi, [rsp + 12]
lea rdx, [rsp + 16]
lea rcx, [rsp + 24]
call qword ptr [rip + __rust_maybe_catch_panic@GOTPCREL]
test eax, eax
je .LBB2_1
mov rdi, -1
call qword ptr [rip + std::panicking::update_panic_count@GOTPCREL]
mov r14, qword ptr [rsp + 16]
mov rbx, qword ptr [rsp + 24]
mov rdi, r14
call qword ptr [rbx]
mov rsi, qword ptr [rbx + 8]
mov ebp, 13
test rsi, rsi
je .LBB2_5
mov rdx, qword ptr [rbx + 16]
mov rdi, r14
call qword ptr [rip + __rust_dealloc@GOTPCREL]
jmp .LBB2_5
.LBB2_1:
mov ebp, dword ptr [rsp + 12]
.LBB2_5:
mov eax, ebp
add rsp, 32
pop rbx
pop r14
pop rbp
ret
mov rbp, rax
mov rdi, r14
mov rsi, rbx
call alloc::alloc::box_free
mov rdi, rbp
call _Unwind_Resume@PLT
ud2
This appears to be a constant overhead every time catch_unwind
is used (e.g. see https://gcc.godbolt.org/z/bAvN24). Maybe we are inlining too much ?