Skip to content

Commit c4eb077

Browse files
committed
Ensure we codegen and don't internalize the entrypoint
1 parent 9cd918b commit c4eb077

File tree

6 files changed

+44
-14
lines changed

6 files changed

+44
-14
lines changed

compiler/rustc_middle/src/mir/mono.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,8 @@ impl<'tcx> MonoItem<'tcx> {
143143
};
144144

145145
// Similarly, the executable entrypoint must be instantiated exactly once.
146-
if let Some((entry_def_id, _)) = tcx.entry_fn(()) {
147-
if instance.def_id() == entry_def_id {
148-
return InstantiationMode::GloballyShared { may_conflict: false };
149-
}
146+
if tcx.is_entrypoint(instance.def_id()) {
147+
return InstantiationMode::GloballyShared { may_conflict: false };
150148
}
151149

152150
// If the function is #[naked] or contains any other attribute that requires exactly-once

compiler/rustc_middle/src/ty/context.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3402,6 +3402,20 @@ impl<'tcx> TyCtxt<'tcx> {
34023402
pub fn do_not_recommend_impl(self, def_id: DefId) -> bool {
34033403
self.get_diagnostic_attr(def_id, sym::do_not_recommend).is_some()
34043404
}
3405+
3406+
/// Whether this def is one of the special bin crate entrypoint functions that must have a
3407+
/// monomorphization and also not be internalized in the bin crate.
3408+
pub fn is_entrypoint(self, def_id: DefId) -> bool {
3409+
if self.is_lang_item(def_id, LangItem::Start) {
3410+
return true;
3411+
}
3412+
if let Some((entry_def_id, _)) = self.entry_fn(())
3413+
&& entry_def_id == def_id
3414+
{
3415+
return true;
3416+
}
3417+
false
3418+
}
34053419
}
34063420

34073421
/// Parameter attributes that can only be determined by examining the body of a function instead

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,6 +1582,15 @@ impl<'v> RootCollector<'_, 'v> {
15821582
return;
15831583
};
15841584

1585+
let main_instance = Instance::mono(self.tcx, main_def_id);
1586+
if self.tcx.should_codegen_locally(main_instance) {
1587+
self.output.push(create_fn_mono_item(
1588+
self.tcx,
1589+
main_instance,
1590+
self.tcx.def_span(main_def_id),
1591+
));
1592+
}
1593+
15851594
let Some(start_def_id) = self.tcx.lang_items().start_fn() else {
15861595
self.tcx.dcx().emit_fatal(errors::StartNotFound);
15871596
};

compiler/rustc_monomorphize/src/partitioning.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -223,11 +223,7 @@ where
223223
// So even if its mode is LocalCopy, we need to treat it like a root.
224224
match mono_item.instantiation_mode(cx.tcx) {
225225
InstantiationMode::GloballyShared { .. } => {}
226-
InstantiationMode::LocalCopy => {
227-
if !cx.tcx.is_lang_item(mono_item.def_id(), LangItem::Start) {
228-
continue;
229-
}
230-
}
226+
InstantiationMode::LocalCopy => continue,
231227
}
232228

233229
let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
@@ -821,10 +817,9 @@ fn mono_item_visibility<'tcx>(
821817
| InstanceKind::FnPtrAddrShim(..) => return Visibility::Hidden,
822818
};
823819

824-
// The `start_fn` lang item is actually a monomorphized instance of a
825-
// function in the standard library, used for the `main` function. We don't
826-
// want to export it so we tag it with `Hidden` visibility but this symbol
827-
// is only referenced from the actual `main` symbol which we unfortunately
820+
// Both the `start_fn` lang item and `main` itself should not be exported,
821+
// so we give them with `Hidden` visibility but these symbols are
822+
// only referenced from the actual `main` symbol which we unfortunately
828823
// don't know anything about during partitioning/collection. As a result we
829824
// forcibly keep this symbol out of the `internalization_candidates` set.
830825
//
@@ -834,7 +829,7 @@ fn mono_item_visibility<'tcx>(
834829
// from the `main` symbol we'll generate later.
835830
//
836831
// This may be fixable with a new `InstanceKind` perhaps? Unsure!
837-
if tcx.is_lang_item(def_id, LangItem::Start) {
832+
if tcx.is_entrypoint(def_id) {
838833
*can_be_internalized = false;
839834
return Visibility::Hidden;
840835
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
pub fn boilerplate() {}
2+
3+
#[inline]
4+
pub fn local_codegen() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//@ run-pass
2+
//@ aux-build:main_functions.rs
3+
//@ compile-flags: -Ccodegen-units=1024
4+
5+
// This is a regression test for https://github.com/rust-lang/rust/issues/144052.
6+
// Entrypoint functions call each other in ways that CGU partitioning doesn't know about. So there
7+
// is a special check to not internalize any of them. But internalizing them can be okay if there
8+
// are few enough CGUs, so we use a lot of CGUs in this test to hit the bad case.
9+
10+
extern crate main_functions;
11+
pub use main_functions::local_codegen as main;

0 commit comments

Comments
 (0)