Skip to content

Commit d3b0480

Browse files
authored
Rollup merge of rust-lang#70467 - wesleywiser:invoke-vs-call, r=nagisa
Use `call` instead of `invoke` for functions that cannot unwind The `FnAbi` now knows if the function is allowed to unwind. If a function isn't allowed to unwind, we can use a `call` instead of an `invoke`. This resolves an issue when calling LLVM intrinsics which cannot unwind LLVM will generate an error if you attempt to invoke them so we need to ignore cleanup blocks in codegen and generate a call instead. Fixes rust-lang#69911 r? @eddyb cc @rust-lang/wg-ffi-unwind
2 parents b2c1a60 + 8da26e0 commit d3b0480

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

src/librustc_codegen_ssa/mir/block.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
111111
destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
112112
cleanup: Option<mir::BasicBlock>,
113113
) {
114-
if let Some(cleanup) = cleanup {
114+
// If there is a cleanup block and the function we're calling can unwind, then
115+
// do an invoke, otherwise do a call.
116+
if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
115117
let ret_bx = if let Some((_, target)) = destination {
116118
fx.blocks[target]
117119
} else {

src/test/codegen/c-variadic.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,38 @@ extern "C" {
1616
#[unwind(aborts)] // FIXME(#58794)
1717
pub unsafe extern "C" fn use_foreign_c_variadic_0() {
1818
// Ensure that we correctly call foreign C-variadic functions.
19-
// CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM:i32( signext)?]] 0)
19+
// CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM:i32( signext)?]] 0)
2020
foreign_c_variadic_0(0);
21-
// CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42)
21+
// CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42)
2222
foreign_c_variadic_0(0, 42i32);
23-
// CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024)
23+
// CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024)
2424
foreign_c_variadic_0(0, 42i32, 1024i32);
25-
// CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0)
25+
// CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0)
2626
foreign_c_variadic_0(0, 42i32, 1024i32, 0i32);
2727
}
2828

2929
// Ensure that we do not remove the `va_list` passed to the foreign function when
3030
// removing the "spoofed" `VaListImpl` that is used by Rust defined C-variadics.
3131
#[unwind(aborts)] // FIXME(#58794)
3232
pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) {
33-
// CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap)
33+
// CHECK: call void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap)
3434
foreign_c_variadic_1(ap);
3535
}
3636

3737
#[unwind(aborts)] // FIXME(#58794)
3838
pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) {
39-
// CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 42)
39+
// CHECK: call void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 42)
4040
foreign_c_variadic_1(ap, 42i32);
4141
}
4242
#[unwind(aborts)] // FIXME(#58794)
4343
pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) {
44-
// CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42)
44+
// CHECK: call void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42)
4545
foreign_c_variadic_1(ap, 2i32, 42i32);
4646
}
4747

4848
#[unwind(aborts)] // FIXME(#58794)
4949
pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) {
50-
// CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42, [[PARAM]] 0)
50+
// CHECK: call void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42, [[PARAM]] 0)
5151
foreign_c_variadic_1(ap, 2i32, 42i32, 0i32);
5252
}
5353

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// compile-flags: -C no-prepopulate-passes
2+
3+
#![feature(link_llvm_intrinsics)]
4+
#![crate_type = "lib"]
5+
6+
struct A;
7+
8+
impl Drop for A {
9+
fn drop(&mut self) {
10+
println!("A");
11+
}
12+
}
13+
14+
extern {
15+
#[link_name = "llvm.sqrt.f32"]
16+
fn sqrt(x: f32) -> f32;
17+
}
18+
19+
pub fn do_call() {
20+
let _a = A;
21+
22+
unsafe {
23+
// Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them
24+
// CHECK: call float @llvm.sqrt.f32(float 4.000000e+00
25+
sqrt(4.0);
26+
}
27+
}

0 commit comments

Comments
 (0)