Fix cases where std accidentally relied on inline(never)
This commit is contained in:
parent
2b399b5275
commit
e559172249
4 changed files with 37 additions and 11 deletions
|
@ -22,6 +22,18 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This just reproduces the logic from Instance::requires_inline.
|
||||||
|
match tcx.def_kind(def_id) {
|
||||||
|
DefKind::Ctor(..) | DefKind::Closure => return true,
|
||||||
|
DefKind::Fn | DefKind::AssocFn => {}
|
||||||
|
_ => return false,
|
||||||
|
}
|
||||||
|
|
||||||
|
// From this point on, it is valid to return true or false.
|
||||||
|
if tcx.sess.opts.unstable_opts.cross_crate_inline_threshold == InliningThreshold::Always {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Obey source annotations first; this is important because it means we can use
|
// Obey source annotations first; this is important because it means we can use
|
||||||
// #[inline(never)] to force code generation.
|
// #[inline(never)] to force code generation.
|
||||||
match codegen_fn_attrs.inline {
|
match codegen_fn_attrs.inline {
|
||||||
|
@ -30,13 +42,6 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This just reproduces the logic from Instance::requires_inline.
|
|
||||||
match tcx.def_kind(def_id) {
|
|
||||||
DefKind::Ctor(..) | DefKind::Closure => return true,
|
|
||||||
DefKind::Fn | DefKind::AssocFn => {}
|
|
||||||
_ => return false,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't do any inference when incremental compilation is enabled; the additional inlining that
|
// Don't do any inference when incremental compilation is enabled; the additional inlining that
|
||||||
// inference permits also creates more work for small edits.
|
// inference permits also creates more work for small edits.
|
||||||
if tcx.sess.opts.incremental.is_some() {
|
if tcx.sess.opts.incremental.is_some() {
|
||||||
|
|
|
@ -176,6 +176,7 @@ use rustc_middle::mir::visit::Visitor as MirVisitor;
|
||||||
use rustc_middle::mir::{self, Location};
|
use rustc_middle::mir::{self, Location};
|
||||||
use rustc_middle::query::TyCtxtAt;
|
use rustc_middle::query::TyCtxtAt;
|
||||||
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
|
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
|
||||||
|
use rustc_middle::ty::layout::ValidityRequirement;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, AssocKind, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable,
|
self, AssocKind, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable,
|
||||||
|
@ -923,6 +924,21 @@ fn visit_instance_use<'tcx>(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The intrinsics assert_inhabited, assert_zero_valid, and assert_mem_uninitialized_valid will
|
||||||
|
// be lowered in codegen to nothing or a call to panic_nounwind. So if we encounter any
|
||||||
|
// of those intrinsics, we need to include a mono item for panic_nounwind, else we may try to
|
||||||
|
// codegen a call to that function without generating code for the function itself.
|
||||||
|
if let ty::InstanceDef::Intrinsic(def_id) = instance.def {
|
||||||
|
let name = tcx.item_name(def_id);
|
||||||
|
if let Some(_requirement) = ValidityRequirement::from_intrinsic(name) {
|
||||||
|
let def_id = tcx.lang_items().get(LangItem::PanicNounwind).unwrap();
|
||||||
|
let panic_instance = Instance::mono(tcx, def_id);
|
||||||
|
if should_codegen_locally(tcx, &panic_instance) {
|
||||||
|
output.push(create_fn_mono_item(tcx, panic_instance, source));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match instance.def {
|
match instance.def {
|
||||||
ty::InstanceDef::Virtual(..) | ty::InstanceDef::Intrinsic(_) => {
|
ty::InstanceDef::Virtual(..) | ty::InstanceDef::Intrinsic(_) => {
|
||||||
if !is_direct_call {
|
if !is_direct_call {
|
||||||
|
|
|
@ -212,11 +212,17 @@ where
|
||||||
let cgu_name_cache = &mut FxHashMap::default();
|
let cgu_name_cache = &mut FxHashMap::default();
|
||||||
|
|
||||||
for mono_item in mono_items {
|
for mono_item in mono_items {
|
||||||
// Handle only root items directly here. Inlined items are handled at
|
// Handle only root (GloballyShared) items directly here. Inlined (LocalCopy) items
|
||||||
// the bottom of the loop based on reachability.
|
// are handled at the bottom of the loop based on reachability, with one exception.
|
||||||
|
// The #[lang = "start"] item is the program entrypoint, so there are no calls to it in MIR.
|
||||||
|
// So even if its mode is LocalCopy, we need to treat it like a root.
|
||||||
match mono_item.instantiation_mode(cx.tcx) {
|
match mono_item.instantiation_mode(cx.tcx) {
|
||||||
InstantiationMode::GloballyShared { .. } => {}
|
InstantiationMode::GloballyShared { .. } => {}
|
||||||
InstantiationMode::LocalCopy => continue,
|
InstantiationMode::LocalCopy => {
|
||||||
|
if Some(mono_item.def_id()) != cx.tcx.lang_items().start_fn() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
|
let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
|
||||||
|
|
|
@ -155,7 +155,6 @@ fn lang_start_internal(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[inline(never)]
|
|
||||||
#[lang = "start"]
|
#[lang = "start"]
|
||||||
fn lang_start<T: crate::process::Termination + 'static>(
|
fn lang_start<T: crate::process::Termination + 'static>(
|
||||||
main: fn() -> T,
|
main: fn() -> T,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue