Add primary marker on codegen unit and generate main wrapper on primary codegen.
This is the codegen part of changes extracted from #84062.
This add a marker called `primary` on each codegen units, where exactly one codegen unit will be `primary = true` at a time. This specific codegen unit will take charge of generating `main` wrapper when `main` is imported from a foreign crate after the implementation of RFC 1260.
cc #28937
I'm not sure who should i ask for review for codegen changes, so feel free to reassign.
r? `@nagisa`
if !cx.codegen_unit().contains_item(&MonoItem::Fn(instance)) {
return None;
}
- } else {
- // FIXME: Add support for non-local main fn codegen
- let span = cx.tcx().main_def.unwrap().span;
- let n = 28937;
- cx.sess()
- .struct_span_err(span, "entry symbol `main` from foreign crate is not yet supported.")
- .note(&format!(
- "see issue #{} <https://github.com/rust-lang/rust/issues/{}> \
- for more information",
- n, n,
- ))
- .emit();
- cx.sess().abort_if_errors();
- bug!();
+ } else if !cx.codegen_unit().is_primary() {
+ // We want to create the wrapper only when the codegen unit is the primary one
+ return None;
}
let main_llfn = cx.get_fn_addr(instance);
name: Symbol,
items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>,
size_estimate: Option<usize>,
+ primary: bool,
}
/// Specifies the linkage type for a `MonoItem`.
impl<'tcx> CodegenUnit<'tcx> {
pub fn new(name: Symbol) -> CodegenUnit<'tcx> {
- CodegenUnit { name, items: Default::default(), size_estimate: None }
+ CodegenUnit { name, items: Default::default(), size_estimate: None, primary: false }
}
pub fn name(&self) -> Symbol {
self.name = name;
}
+ pub fn is_primary(&self) -> bool {
+ self.primary
+ }
+
+ pub fn make_primary(&mut self) {
+ self.primary = true;
+ }
+
pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
&self.items
}
name,
// The size estimate is not relevant to the hash
size_estimate: _,
+ primary: _,
} = *self;
name.hash_stable(hcx, hasher);
let (codegen_units, _) = tcx.sess.time("partition_and_assert_distinct_symbols", || {
sync::join(
|| {
- &*tcx.arena.alloc_from_iter(partition(
+ let mut codegen_units = partition(
tcx,
&mut items.iter().cloned(),
tcx.sess.codegen_units(),
&inlining_map,
- ))
+ );
+ codegen_units[0].make_primary();
+ &*tcx.arena.alloc_from_iter(codegen_units)
},
|| assert_symbols_are_distinct(tcx, items.iter()),
)
-// build-fail
+// run-pass
// aux-build:main_functions.rs
#![feature(imported_main)]
extern crate main_functions;
-pub use main_functions::boilerplate as main; //~ ERROR entry symbol `main` from foreign crate
-
-// FIXME: Should be run-pass
+pub use main_functions::boilerplate as main;
+++ /dev/null
-error: entry symbol `main` from foreign crate is not yet supported.
- --> $DIR/imported_main_from_extern_crate.rs:7:9
- |
-LL | pub use main_functions::boilerplate as main;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #28937 <https://github.com/rust-lang/rust/issues/28937> for more information
-
-error: aborting due to previous error
-