Skip to content

Commit 097e9e5

Browse files
committed
Add can_unwind field to FnAbi
This is a pure refactoring with no behavior changes.
1 parent a80ec3b commit 097e9e5

File tree

3 files changed

+60
-44
lines changed

3 files changed

+60
-44
lines changed

src/librustc_codegen_llvm/attributes.rs

+1-41
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ use rustc_middle::ty::query::Providers;
1313
use rustc_middle::ty::{self, Ty, TyCtxt};
1414
use rustc_session::config::{OptLevel, Sanitizer};
1515
use rustc_session::Session;
16-
use rustc_target::abi::call::Conv;
17-
use rustc_target::spec::PanicStrategy;
1816

1917
use crate::abi::FnAbi;
2018
use crate::attributes;
@@ -315,45 +313,7 @@ pub fn from_fn_attrs(
315313
}
316314
sanitize(cx, codegen_fn_attrs.flags, llfn);
317315

318-
unwind(
319-
llfn,
320-
if cx.tcx.sess.panic_strategy() != PanicStrategy::Unwind {
321-
// In panic=abort mode we assume nothing can unwind anywhere, so
322-
// optimize based on this!
323-
false
324-
} else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
325-
// If a specific #[unwind] attribute is present, use that.
326-
true
327-
} else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
328-
// Special attribute for allocator functions, which can't unwind.
329-
false
330-
} else {
331-
if fn_abi.conv == Conv::Rust {
332-
// Any Rust method (or `extern "Rust" fn` or `extern
333-
// "rust-call" fn`) is explicitly allowed to unwind
334-
// (unless it has no-unwind attribute, handled above).
335-
true
336-
} else {
337-
// Anything else is either:
338-
//
339-
// 1. A foreign item using a non-Rust ABI (like `extern "C" { fn foo(); }`), or
340-
//
341-
// 2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`).
342-
//
343-
// Foreign items (case 1) are assumed to not unwind; it is
344-
// UB otherwise. (At least for now; see also
345-
// rust-lang/rust#63909 and Rust RFC 2753.)
346-
//
347-
// Items defined in Rust with non-Rust ABIs (case 2) are also
348-
// not supposed to unwind. Whether this should be enforced
349-
// (versus stating it is UB) and *how* it would be enforced
350-
// is currently under discussion; see rust-lang/rust#58794.
351-
//
352-
// In either case, we mark item as explicitly nounwind.
353-
false
354-
}
355-
},
356-
);
316+
unwind(llfn, fn_abi.can_unwind);
357317

358318
// Always annotate functions with the target-cpu they are compiled for.
359319
// Without this, ThinLTO won't inline Rust functions into Clang generated

src/librustc_middle/ty/layout.rs

+57-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::ich::StableHashingContext;
2+
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
23
use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
34
use crate::ty::subst::Subst;
45
use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
@@ -15,7 +16,7 @@ use rustc_target::abi::call::{
1516
ArgAbi, ArgAttribute, ArgAttributes, Conv, FnAbi, PassMode, Reg, RegKind,
1617
};
1718
pub use rustc_target::abi::*;
18-
use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec};
19+
use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy};
1920

2021
use std::cmp;
2122
use std::fmt;
@@ -2368,11 +2369,55 @@ where
23682369
sig: ty::PolyFnSig<'tcx>,
23692370
extra_args: &[Ty<'tcx>],
23702371
caller_location: Option<Ty<'tcx>>,
2372+
codegen_fn_attr_flags: CodegenFnAttrFlags,
23712373
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
23722374
) -> Self;
23732375
fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi);
23742376
}
23752377

2378+
fn fn_can_unwind(
2379+
panic_strategy: PanicStrategy,
2380+
codegen_fn_attr_flags: CodegenFnAttrFlags,
2381+
call_conv: Conv,
2382+
) -> bool {
2383+
if panic_strategy != PanicStrategy::Unwind {
2384+
// In panic=abort mode we assume nothing can unwind anywhere, so
2385+
// optimize based on this!
2386+
false
2387+
} else if codegen_fn_attr_flags.contains(CodegenFnAttrFlags::UNWIND) {
2388+
// If a specific #[unwind] attribute is present, use that.
2389+
true
2390+
} else if codegen_fn_attr_flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
2391+
// Special attribute for allocator functions, which can't unwind.
2392+
false
2393+
} else {
2394+
if call_conv == Conv::Rust {
2395+
// Any Rust method (or `extern "Rust" fn` or `extern
2396+
// "rust-call" fn`) is explicitly allowed to unwind
2397+
// (unless it has no-unwind attribute, handled above).
2398+
true
2399+
} else {
2400+
// Anything else is either:
2401+
//
2402+
// 1. A foreign item using a non-Rust ABI (like `extern "C" { fn foo(); }`), or
2403+
//
2404+
// 2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`).
2405+
//
2406+
// Foreign items (case 1) are assumed to not unwind; it is
2407+
// UB otherwise. (At least for now; see also
2408+
// rust-lang/rust#63909 and Rust RFC 2753.)
2409+
//
2410+
// Items defined in Rust with non-Rust ABIs (case 2) are also
2411+
// not supposed to unwind. Whether this should be enforced
2412+
// (versus stating it is UB) and *how* it would be enforced
2413+
// is currently under discussion; see rust-lang/rust#58794.
2414+
//
2415+
// In either case, we mark item as explicitly nounwind.
2416+
false
2417+
}
2418+
}
2419+
}
2420+
23762421
impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>>
23772422
where
23782423
C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
@@ -2382,7 +2427,12 @@ where
23822427
+ HasParamEnv<'tcx>,
23832428
{
23842429
fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
2385-
call::FnAbi::new_internal(cx, sig, extra_args, None, |ty, _| ArgAbi::new(cx.layout_of(ty)))
2430+
// Assume that fn pointers may always unwind
2431+
let codegen_fn_attr_flags = CodegenFnAttrFlags::UNWIND;
2432+
2433+
call::FnAbi::new_internal(cx, sig, extra_args, None, codegen_fn_attr_flags, |ty, _| {
2434+
ArgAbi::new(cx.layout_of(ty))
2435+
})
23862436
}
23872437

23882438
fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
@@ -2394,7 +2444,9 @@ where
23942444
None
23952445
};
23962446

2397-
call::FnAbi::new_internal(cx, sig, extra_args, caller_location, |ty, arg_idx| {
2447+
let attrs = cx.tcx().codegen_fn_attrs(instance.def_id()).flags;
2448+
2449+
call::FnAbi::new_internal(cx, sig, extra_args, caller_location, attrs, |ty, arg_idx| {
23982450
let mut layout = cx.layout_of(ty);
23992451
// Don't pass the vtable, it's not an argument of the virtual fn.
24002452
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -2450,6 +2502,7 @@ where
24502502
sig: ty::PolyFnSig<'tcx>,
24512503
extra_args: &[Ty<'tcx>],
24522504
caller_location: Option<Ty<'tcx>>,
2505+
codegen_fn_attr_flags: CodegenFnAttrFlags,
24532506
mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgAbi<'tcx, Ty<'tcx>>,
24542507
) -> Self {
24552508
debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args);
@@ -2639,6 +2692,7 @@ where
26392692
c_variadic: sig.c_variadic,
26402693
fixed_count: inputs.len(),
26412694
conv,
2695+
can_unwind: fn_can_unwind(cx.tcx().sess.panic_strategy(), codegen_fn_attr_flags, conv),
26422696
};
26432697
fn_abi.adjust_for_abi(cx, sig.abi);
26442698
fn_abi

src/librustc_target/abi/call/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,8 @@ pub struct FnAbi<'a, Ty> {
546546
pub fixed_count: usize,
547547

548548
pub conv: Conv,
549+
550+
pub can_unwind: bool,
549551
}
550552

551553
impl<'a, Ty> FnAbi<'a, Ty> {

0 commit comments

Comments
 (0)