do not make function addresses unique with cross_crate_inline_threshold=always (even if that breaks backtraces)
This commit is contained in:
parent
5cab8ae4a4
commit
dec5b463fb
@ -24,6 +24,7 @@
|
|||||||
Instance, Ty, TyCtxt,
|
Instance, Ty, TyCtxt,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use rustc_session::config::InliningThreshold;
|
||||||
use rustc_span::def_id::{CrateNum, DefId};
|
use rustc_span::def_id::{CrateNum, DefId};
|
||||||
use rustc_span::{Span, SpanData, Symbol};
|
use rustc_span::{Span, SpanData, Symbol};
|
||||||
use rustc_target::abi::{Align, Size};
|
use rustc_target::abi::{Align, Size};
|
||||||
@ -1525,24 +1526,29 @@ fn get_global_alloc_salt(
|
|||||||
instance: Option<ty::Instance<'tcx>>,
|
instance: Option<ty::Instance<'tcx>>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let unique = if let Some(instance) = instance {
|
let unique = if let Some(instance) = instance {
|
||||||
// Functions cannot be identified by pointers, as asm-equal functions can get deduplicated
|
// Functions cannot be identified by pointers, as asm-equal functions can get
|
||||||
// by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be
|
// deduplicated by the linker (we set the "unnamed_addr" attribute for LLVM) and
|
||||||
// duplicated across crates. We thus generate a new `AllocId` for every mention of a
|
// functions can be duplicated across crates. We thus generate a new `AllocId` for every
|
||||||
// function. This means that `main as fn() == main as fn()` is false, while `let x = main as
|
// mention of a function. This means that `main as fn() == main as fn()` is false, while
|
||||||
// fn(); x == x` is true. However, as a quality-of-life feature it can be useful to identify
|
// `let x = main as fn(); x == x` is true. However, as a quality-of-life feature it can
|
||||||
// certain functions uniquely, e.g. for backtraces. So we identify whether codegen will
|
// be useful to identify certain functions uniquely, e.g. for backtraces. So we identify
|
||||||
// actually emit duplicate functions. It does that when they have non-lifetime generics, or
|
// whether codegen will actually emit duplicate functions. It does that when they have
|
||||||
// when they can be inlined. All other functions are given a unique address.
|
// non-lifetime generics, or when they can be inlined. All other functions are given a
|
||||||
// This is not a stable guarantee! The `inline` attribute is a hint and cannot be relied
|
// unique address. This is not a stable guarantee! The `inline` attribute is a hint and
|
||||||
// upon for anything. But if we don't do this, backtraces look terrible.
|
// cannot be relied upon for anything. But if we don't do this, the
|
||||||
|
// `__rust_begin_short_backtrace`/`__rust_end_short_backtrace` logic breaks and panic
|
||||||
|
// backtraces look terrible.
|
||||||
let is_generic = instance
|
let is_generic = instance
|
||||||
.args
|
.args
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.any(|kind| !matches!(kind.unpack(), ty::GenericArgKind::Lifetime(_)));
|
.any(|kind| !matches!(kind.unpack(), ty::GenericArgKind::Lifetime(_)));
|
||||||
let can_be_inlined = match ecx.tcx.codegen_fn_attrs(instance.def_id()).inline {
|
let can_be_inlined = matches!(
|
||||||
InlineAttr::Never => false,
|
ecx.tcx.sess.opts.unstable_opts.cross_crate_inline_threshold,
|
||||||
_ => true,
|
InliningThreshold::Always
|
||||||
};
|
) || !matches!(
|
||||||
|
ecx.tcx.codegen_fn_attrs(instance.def_id()).inline,
|
||||||
|
InlineAttr::Never
|
||||||
|
);
|
||||||
!is_generic && !can_be_inlined
|
!is_generic && !can_be_inlined
|
||||||
} else {
|
} else {
|
||||||
// Non-functions are never unique.
|
// Non-functions are never unique.
|
||||||
|
Loading…
Reference in New Issue
Block a user