Skip to content

Commit 2201adc

Browse files
committed
fix nounwind attribute logic
1 parent 4c58535 commit 2201adc

File tree

4 files changed

+46
-10
lines changed

4 files changed

+46
-10
lines changed

src/librustc_codegen_llvm/attributes.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -268,22 +268,18 @@ pub fn from_fn_attrs(
268268
// optimize based on this!
269269
false
270270
} else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
271-
// If a specific #[unwind] attribute is present, use that
271+
// If a specific #[unwind] attribute is present, use that.
272+
// FIXME: We currently assume it can unwind even with `#[unwind(aborts)]`.
272273
true
273274
} else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
274275
// Special attribute for allocator functions, which can't unwind
275276
false
276277
} else if let Some(id) = id {
277278
let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
278-
if cx.tcx.is_foreign_item(id) {
279-
// Foreign items like `extern "C" { fn foo(); }` are assumed not to
279+
if cx.tcx.is_foreign_item(id) && sig.abi != Abi::Rust && sig.abi != Abi::RustCall {
280+
// Foreign non-Rust items like `extern "C" { fn foo(); }` are assumed not to
280281
// unwind
281282
false
282-
} else if sig.abi != Abi::Rust && sig.abi != Abi::RustCall {
283-
// Any items defined in Rust that *don't* have the `extern` ABI are
284-
// defined to not unwind. We insert shims to abort if an unwind
285-
// happens to enforce this.
286-
false
287283
} else {
288284
// Anything else defined in Rust is assumed that it can possibly
289285
// unwind

src/test/codegen/extern-functions.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,36 @@
66
extern {
77
// CHECK: Function Attrs: nounwind
88
// CHECK-NEXT: declare void @extern_fn
9-
fn extern_fn();
10-
// CHECK-NOT: Function Attrs: nounwind
9+
fn extern_fn(); // assumed not to unwind
10+
// CHECK-NOT: nounwind
1111
// CHECK: declare void @unwinding_extern_fn
1212
#[unwind(allowed)]
1313
fn unwinding_extern_fn();
14+
// CHECK-NOT: nounwind
15+
// CHECK: declare void @aborting_extern_fn
16+
#[unwind(aborts)]
17+
fn aborting_extern_fn(); // FIXME: we don't have the attribute here
18+
}
19+
20+
extern "Rust" {
21+
// CHECK-NOT: nounwind
22+
// CHECK: declare void @rust_extern_fn
23+
fn rust_extern_fn();
24+
// CHECK-NOT: nounwind
25+
// CHECK: declare void @rust_unwinding_extern_fn
26+
#[unwind(allowed)]
27+
fn rust_unwinding_extern_fn();
28+
// CHECK-NOT: nounwind
29+
// CHECK: declare void @rust_aborting_extern_fn
30+
#[unwind(aborts)]
31+
fn rust_aborting_extern_fn(); // FIXME: we don't have the attribute here
1432
}
1533

1634
pub unsafe fn force_declare() {
1735
extern_fn();
1836
unwinding_extern_fn();
37+
aborting_extern_fn();
38+
rust_extern_fn();
39+
rust_unwinding_extern_fn();
40+
rust_aborting_extern_fn();
1941
}

src/test/codegen/nounwind-extern.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@
22

33
#![crate_type = "lib"]
44

5+
// The `nounwind` attribute does not get added by rustc; it is present here because LLVM
6+
// analyses determine that this function does not unwind.
7+
58
// CHECK: Function Attrs: norecurse nounwind
69
pub extern fn foo() {}

src/test/codegen/unwind-extern.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// compile-flags: -C opt-level=0
2+
3+
#![crate_type = "lib"]
4+
#![feature(unwind_attributes)]
5+
6+
// make sure these all do *not* get the attribute
7+
// CHECK-NOT: nounwind
8+
9+
pub extern fn foo() {} // right now we don't abort-on-panic, so we also shouldn't have `nounwind`
10+
#[unwind(allowed)]
11+
pub extern fn foo_allowed() {}
12+
13+
pub extern "Rust" fn bar() {}
14+
#[unwind(allowed)]
15+
pub extern "Rust" fn bar_allowed() {}

0 commit comments

Comments
 (0)