Skip to content

Commit af480fa

Browse files
committed
Made some progress, found what looks like a miscompile
1 parent 9fc5b9f commit af480fa

File tree

13 files changed

+102
-51
lines changed

13 files changed

+102
-51
lines changed

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+25
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,31 @@ fn exported_symbols_provider_local(
390390
}
391391
}
392392

393+
if tcx.building_mir_only_rlib() {
394+
for def_id in tcx.mir_keys(()) {
395+
if !matches!(tcx.def_kind(def_id.to_def_id()), DefKind::Static(_)) {
396+
continue;
397+
}
398+
if tcx.is_reachable_non_generic(def_id.to_def_id()) {
399+
continue;
400+
}
401+
let codegen_attrs = tcx.codegen_fn_attrs(def_id.to_def_id());
402+
symbols.push((
403+
ExportedSymbol::NonGeneric(def_id.to_def_id()),
404+
SymbolExportInfo {
405+
level: symbol_export_level(tcx, def_id.to_def_id()),
406+
kind: if codegen_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
407+
SymbolExportKind::Tls
408+
} else {
409+
SymbolExportKind::Data
410+
},
411+
used: true,
412+
used_compiler: true,
413+
},
414+
));
415+
}
416+
}
417+
393418
// Sort so we get a stable incr. comp. hash.
394419
symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx));
395420

compiler/rustc_interface/src/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ fn test_unstable_options_tracking_hash() {
776776
tracked!(mir_emit_retag, true);
777777
tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
778778
tracked!(mir_keep_place_mention, true);
779-
tracked!(mir_only_libs, true);
779+
tracked!(mir_only_rlibs, true);
780780
tracked!(mir_opt_level, Some(4));
781781
tracked!(move_size_limit, Some(4096));
782782
tracked!(mutable_noalias, false);

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+8
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,14 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
502502
tcx.untracked().cstore.freeze();
503503
tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).iter_crate_data().map(|(cnum, _)| cnum))
504504
},
505+
mir_only_crates: |tcx, ()| {
506+
tcx.untracked().cstore.freeze();
507+
let store = CStore::from_tcx(tcx);
508+
let crates = store
509+
.iter_crate_data()
510+
.filter_map(|(cnum, data)| if data.root.is_mir_only { Some(cnum) } else { None });
511+
tcx.arena.alloc_from_iter(crates)
512+
},
505513
..providers.queries
506514
};
507515
provide_extern(&mut providers.extern_queries);

compiler/rustc_metadata/src/rmeta/encoder.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
727727
impls,
728728
incoherent_impls,
729729
exported_symbols,
730+
is_mir_only: tcx.building_mir_only_rlib(),
730731
interpret_alloc_index,
731732
tables,
732733
syntax_contexts,
@@ -1038,7 +1039,7 @@ fn should_encode_mir(
10381039
def_id: LocalDefId,
10391040
) -> (bool, bool) {
10401041
let opts = &tcx.sess.opts;
1041-
let mir_required = opts.unstable_opts.always_encode_mir || opts.unstable_opts.mir_only_libs;
1042+
let mir_required = opts.unstable_opts.always_encode_mir || tcx.building_mir_only_rlib();
10421043
match tcx.def_kind(def_id) {
10431044
// Constructors
10441045
DefKind::Ctor(_, _) => {

compiler/rustc_metadata/src/rmeta/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ pub(crate) struct CrateRoot {
276276
debugger_visualizers: LazyArray<DebuggerVisualizerFile>,
277277

278278
exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
279+
is_mir_only: bool,
279280

280281
syntax_contexts: SyntaxContextTable,
281282
expn_data: ExpnDataTable,

compiler/rustc_middle/src/mir/mono.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl<'tcx> MonoItem<'tcx> {
9999

100100
pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode {
101101
// Always do LocalCopy codegen when building a MIR-only rlib
102-
if tcx.building_mir_only_lib() {
102+
if tcx.building_mir_only_rlib() {
103103
return InstantiationMode::LocalCopy;
104104
}
105105
let generate_cgu_internal_copies = tcx
@@ -112,17 +112,6 @@ impl<'tcx> MonoItem<'tcx> {
112112

113113
match *self {
114114
MonoItem::Fn(ref instance) => {
115-
// See the check in MirUsedCollector for building_mir_only_bin for background.
116-
// Here, we need to give the symbols that the collector feeds to use GloballyShared
117-
// linkage so that CGU partitioning doesn't try to assign them lazily, then find no
118-
// uses of them. They might only be used by an upstream crate, so we need to force
119-
// codegen, which is what GloballyShared does.
120-
if tcx.building_mir_only_bin()
121-
&& tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator()
122-
{
123-
return InstantiationMode::GloballyShared { may_conflict: false };
124-
}
125-
126115
let entry_def_id = tcx.entry_fn(()).map(|(id, _)| id);
127116
// If this function isn't inlined or otherwise has an extern
128117
// indicator, then we'll be creating a globally shared version.

compiler/rustc_middle/src/query/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -2195,6 +2195,11 @@ rustc_queries! {
21952195
desc { "whether the item should be made inlinable across crates" }
21962196
separate_provide_extern
21972197
}
2198+
2199+
query mir_only_crates(_: ()) -> &'tcx [CrateNum] {
2200+
eval_always
2201+
desc { "fetching all foreign crates built in mir-only mode" }
2202+
}
21982203
}
21992204

22002205
rustc_query_append! { define_callbacks! }

compiler/rustc_middle/src/ty/context.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -1029,12 +1029,8 @@ impl<'tcx> TyCtxt<'tcx> {
10291029
self.sess.dcx()
10301030
}
10311031

1032-
pub fn building_mir_only_lib(self) -> bool {
1033-
self.sess.opts.unstable_opts.mir_only_libs && self.crate_types() == &[CrateType::Rlib]
1034-
}
1035-
1036-
pub fn building_mir_only_bin(self) -> bool {
1037-
self.sess.opts.unstable_opts.mir_only_libs && self.crate_types() == &[CrateType::Executable]
1032+
pub fn building_mir_only_rlib(self) -> bool {
1033+
self.sess.opts.unstable_opts.mir_only_rlibs && self.crate_types() == &[CrateType::Rlib]
10381034
}
10391035
}
10401036

compiler/rustc_monomorphize/src/collector.rs

+37-20
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ use rustc_middle::ty::{
185185
};
186186
use rustc_middle::ty::{GenericArgKind, GenericArgs};
187187
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
188+
use rustc_session::config::CrateType;
188189
use rustc_session::config::EntryFnType;
189190
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
190191
use rustc_session::Limit;
@@ -317,6 +318,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
317318
}
318319

319320
collector.push_extra_entry_roots();
321+
collector.push_extra_roots_from_mir_only_rlibs();
320322
}
321323

322324
// We can only codegen items that are instantiable - items all of
@@ -976,15 +978,15 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
976978
};
977979

978980
if tcx.is_foreign_item(def_id) {
979-
if tcx.sess.opts.unstable_opts.mir_only_libs {
981+
if tcx.building_mir_only_rlib() {
980982
return tcx.is_mir_available(instance.def_id());
981983
} else {
982984
// Foreign items are always linked against, there's no way of instantiating them.
983985
return false;
984986
}
985987
}
986988

987-
if tcx.sess.opts.unstable_opts.mir_only_libs {
989+
if tcx.building_mir_only_rlib() {
988990
let has_mir = tcx.is_mir_available(instance.def_id());
989991
return has_mir || matches!(tcx.def_kind(instance.def_id()), DefKind::Static(_));
990992
}
@@ -1281,7 +1283,6 @@ impl<'v> RootCollector<'_, 'v> {
12811283
let Some((main_def_id, EntryFnType::Main { .. })) = self.entry_fn else {
12821284
return;
12831285
};
1284-
12851286
let start_def_id = self.tcx.require_lang_item(LangItem::Start, None);
12861287
let main_ret_ty = self.tcx.fn_sig(main_def_id).no_bound_vars().unwrap().output();
12871288

@@ -1305,34 +1306,50 @@ impl<'v> RootCollector<'_, 'v> {
13051306
.unwrap();
13061307

13071308
self.output.push(create_fn_mono_item(self.tcx, start_instance, DUMMY_SP));
1309+
}
13081310

1311+
fn push_extra_roots_from_mir_only_rlibs(&mut self) {
13091312
// An upstream extern function may be used anywhere in the dependency tree, so we
13101313
// cannot do any reachability analysis on them. We blindly monomorphize every
13111314
// extern function declared anywhere in our dependency tree. We must give them
13121315
// GloballyShared codegen because we don't know if the only call to an upstream
13131316
// extern function is also upstream: We don't have reachability information. All we
13141317
// can do is codegen all extern functions and pray for the linker to delete the
13151318
// ones that are reachable.
1316-
if self.tcx.building_mir_only_bin() {
1317-
for (symbol, _info) in
1318-
self.tcx.crates(()).into_iter().flat_map(|krate| self.tcx.exported_symbols(*krate))
1319-
{
1320-
let def_id = match symbol {
1321-
ExportedSymbol::NonGeneric(def_id) => def_id,
1322-
_ => {
1323-
continue;
1324-
}
1325-
};
1326-
if self.tcx.def_kind(def_id) != DefKind::Fn {
1319+
if !self.tcx.crate_types().iter().any(|c| !matches!(c, CrateType::Rlib)) {
1320+
return;
1321+
}
1322+
1323+
for (symbol, _info) in self
1324+
.tcx
1325+
.mir_only_crates(())
1326+
.into_iter()
1327+
.flat_map(|krate| self.tcx.exported_symbols(*krate))
1328+
{
1329+
let def_id = match symbol {
1330+
ExportedSymbol::NonGeneric(def_id) => def_id,
1331+
ExportedSymbol::ThreadLocalShim(def_id) => {
1332+
let item = MonoItem::Fn(Instance {
1333+
def: InstanceDef::ThreadLocalShim(*def_id),
1334+
args: GenericArgs::empty(),
1335+
});
1336+
self.output.push(respan(DUMMY_SP, item));
13271337
continue;
13281338
}
1329-
let instance = Instance::mono(self.tcx, *def_id);
1330-
// FIXME: This is probably not the right span. What is?
1331-
let item = create_fn_mono_item(self.tcx, instance, DUMMY_SP);
1332-
// FIXME: Do we need this check?
1333-
if !self.output.iter().any(|out| out.node.def_id() == *def_id) {
1334-
self.output.push(item);
1339+
_ => continue,
1340+
};
1341+
match self.tcx.def_kind(def_id) {
1342+
DefKind::Fn | DefKind::AssocFn => {
1343+
let instance = Instance::mono(self.tcx, *def_id);
1344+
let item = create_fn_mono_item(self.tcx, instance, DUMMY_SP);
1345+
if !self.output.iter().any(|out| out.node.def_id() == *def_id) {
1346+
self.output.push(item);
1347+
}
1348+
}
1349+
DefKind::Static(_) => {
1350+
self.output.push(dummy_spanned(MonoItem::Static(*def_id)));
13351351
}
1352+
_ => {}
13361353
}
13371354
}
13381355
}

compiler/rustc_monomorphize/src/partitioning.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,10 @@ fn partition<'tcx, I>(
141141
where
142142
I: Iterator<Item = MonoItem<'tcx>>,
143143
{
144-
if tcx.sess.opts.unstable_opts.mir_only_libs {
145-
assert!(tcx.building_mir_only_lib() || tcx.building_mir_only_bin());
144+
if tcx.building_mir_only_rlib() {
145+
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
146+
let cgu_name = fallback_cgu_name(cgu_name_builder);
147+
return vec![CodegenUnit::new(cgu_name)];
146148
}
147149

148150
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
@@ -169,6 +171,10 @@ where
169171
debug_dump(tcx, "MERGE", &codegen_units);
170172
}
171173

174+
if !codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))) {
175+
bug!("unsorted CGUs");
176+
}
177+
172178
// Make as many symbols "internal" as possible, so LLVM has more freedom to
173179
// optimize.
174180
if !tcx.sess.link_dead_code() {
@@ -191,7 +197,12 @@ where
191197
for cgu in codegen_units.iter() {
192198
names += &format!("- {}\n", cgu.name());
193199
}
194-
bug!("unsorted CGUs:\n{names}");
200+
codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
201+
let mut sorted_names = String::new();
202+
for cgu in codegen_units.iter() {
203+
sorted_names += &format!("- {}\n", cgu.name());
204+
}
205+
bug!("unsorted CGUs:\n{names}\n{sorted_names}");
195206
}
196207

197208
codegen_units
@@ -264,9 +275,6 @@ where
264275
cgu.items_mut()
265276
.insert(mono_item, MonoItemData { inlined: false, linkage, visibility, size_estimate });
266277

267-
if cx.tcx.building_mir_only_lib() {
268-
continue;
269-
}
270278
// Get all inlined items that are reachable from `mono_item` without
271279
// going via another root item. This includes drop-glue, functions from
272280
// external crates, and local functions the definition of which is

compiler/rustc_session/src/options.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1705,8 +1705,8 @@ options! {
17051705
mir_keep_place_mention: bool = (false, parse_bool, [TRACKED],
17061706
"keep place mention MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
17071707
(default: no)"),
1708-
mir_only_libs: bool = (false, parse_bool, [TRACKED],
1709-
"only generate MIR when building libraries (default: no)"),
1708+
mir_only_rlibs: bool = (false, parse_bool, [TRACKED],
1709+
"only generate MIR when building rlibs (default: no)"),
17101710
#[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")]
17111711
mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
17121712
"MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),

library/std/Cargo.toml

-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ repository = "https://github.com/rust-lang/rust.git"
88
description = "The Rust Standard Library"
99
edition = "2021"
1010

11-
[lib]
12-
crate-type = ["dylib", "rlib"]
13-
1411
[dependencies]
1512
alloc = { path = "../alloc", public = true }
1613
cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }

src/bootstrap/src/core/builder.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,10 @@ impl<'a> Builder<'a> {
14071407
rustflags.arg("--cfg=bootstrap");
14081408
}
14091409

1410+
if stage != 0 && mode == Mode::Std {
1411+
rustflags.arg("-Zmir-only-rlibs");
1412+
}
1413+
14101414
if cmd == "clippy" {
14111415
// clippy overwrites sysroot if we pass it to cargo.
14121416
// Pass it directly to clippy instead.

0 commit comments

Comments
 (0)