diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 14d6f0ba147b5..e96cde2b3b03d 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -45,7 +45,7 @@ pub fn crates_export_threshold(crate_types: &[CrateType]) -> SymbolExportLevel { fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap { assert_eq!(cnum, LOCAL_CRATE); - if !tcx.sess.opts.output_types.should_codegen() { + if !tcx.sess.opts.output_types.should_codegen() && !tcx.sess.opts.debugging_opts.metadata_link { return Default::default(); } @@ -164,7 +164,7 @@ fn exported_symbols_provider_local( ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportLevel)] { assert_eq!(cnum, LOCAL_CRATE); - if !tcx.sess.opts.output_types.should_codegen() { + if !tcx.sess.opts.output_types.should_codegen() && !tcx.sess.opts.debugging_opts.metadata_link { return &[]; } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index bea7d0fb81f95..d9276aff37d6a 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -706,6 +706,7 @@ fn test_debugging_options_tracking_hash() { tracked!(instrument_mcount, true); tracked!(link_only, true); tracked!(merge_functions, Some(MergeFunctions::Disabled)); + tracked!(metadata_link, true); tracked!(mir_emit_retag, true); tracked!(mir_opt_level, Some(4)); tracked!(mutable_noalias, Some(true)); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 5c45e4130d2d7..488a1c538dc73 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -815,11 +815,14 @@ fn should_encode_stability(def_kind: DefKind) -> bool { /// /// Return a pair, resp. for CTFE and for LLVM. fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) { + let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir; + let metadata_link = tcx.sess.opts.debugging_opts.metadata_link; + match tcx.def_kind(def_id) { // Constructors DefKind::Ctor(_, _) => { - let mir_opt_base = tcx.sess.opts.output_types.should_codegen() - || tcx.sess.opts.debugging_opts.always_encode_mir; + let mir_opt_base = + tcx.sess.opts.output_types.should_codegen() || always_encode_mir || metadata_link; (true, mir_opt_base) } // Constants @@ -831,10 +834,9 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) { let generics = tcx.generics_of(def_id); let needs_inline = (generics.requires_monomorphization(tcx) || tcx.codegen_fn_attrs(def_id).requests_inline()) - && tcx.sess.opts.output_types.should_codegen(); + && (tcx.sess.opts.output_types.should_codegen() || metadata_link); // Only check the presence of the `const` modifier. let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()); - let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir; (is_const_fn, needs_inline || always_encode_mir) } // Closures can't be const fn. @@ -842,8 +844,7 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) { let generics = tcx.generics_of(def_id); let needs_inline = (generics.requires_monomorphization(tcx) || tcx.codegen_fn_attrs(def_id).requests_inline()) - && tcx.sess.opts.output_types.should_codegen(); - let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir; + && (tcx.sess.opts.output_types.should_codegen() || metadata_link); (false, needs_inline || always_encode_mir) } // Generators require optimized MIR to compute layout. @@ -2020,7 +2021,7 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { /// Used to prefetch queries which will be needed later by metadata encoding. /// Only a subset of the queries are actually prefetched to keep this code smaller. fn prefetch_mir(tcx: TyCtxt<'_>) { - if !tcx.sess.opts.output_types.should_codegen() { + if !tcx.sess.opts.output_types.should_codegen() && !tcx.sess.opts.debugging_opts.metadata_link { // We won't emit MIR, so don't prefetch it. return; } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c9f95ed1224d0..fe97eeded2a9a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1121,6 +1121,8 @@ options! { the same values as the target option of the same name"), meta_stats: bool = (false, parse_bool, [UNTRACKED], "gather metadata statistics (default: no)"), + metadata_link: bool = (false, parse_bool, [TRACKED], + "always emit metadata that's equivalent to metadata,link"), mir_emit_retag: bool = (false, parse_bool, [TRACKED], "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \ (default: no)"), diff --git a/src/test/run-make/pipelined/Makefile b/src/test/run-make/pipelined/Makefile new file mode 100644 index 0000000000000..cf851dc69951b --- /dev/null +++ b/src/test/run-make/pipelined/Makefile @@ -0,0 +1,33 @@ +-include ../../run-make-fulldeps/tools.mk + +O=$(TMPDIR)/together +S=$(TMPDIR)/separate + +all: $O/main $S/main + # Should produce identical output + cmp $O/main $S/main + +# Build with combined --emit metadata,link +$O/main: $O/libmiddle.rlib $O/libleaf.rlib + $(BARE_RUSTC) --out-dir $O main.rs --extern middle=$O/libmiddle.rlib -Ldependency=$O + $O/main + +$O/libmiddle.rlib: middle.rs $O/libleaf.rmeta + $(BARE_RUSTC) --out-dir $O --emit link middle.rs --extern leaf=$O/libleaf.rmeta + +$O/libleaf.rlib $O/libleaf.rmeta: leaf.rs + $(BARE_RUSTC) --out-dir $O --emit metadata,link leaf.rs + +# Build with separate --emit metadata / --emit link +$S/main: $S/libmiddle.rlib $S/libleaf.rlib + $(BARE_RUSTC) --out-dir $S main.rs --extern middle=$S/libmiddle.rlib -Ldependency=$S + $S/main + +$S/libmiddle.rlib: middle.rs $S/libleaf.rmeta + $(BARE_RUSTC) --out-dir $S --emit link middle.rs --extern leaf=$S/libleaf.rmeta + +$S/libleaf.rlib: leaf.rs + $(BARE_RUSTC) --out-dir $S --emit link leaf.rs + +$S/libleaf.rmeta: leaf.rs + $(BARE_RUSTC) --out-dir $S --emit metadata -Zmetadata-link leaf.rs diff --git a/src/test/run-make/pipelined/leaf.rs b/src/test/run-make/pipelined/leaf.rs new file mode 100644 index 0000000000000..6ddcd63d59559 --- /dev/null +++ b/src/test/run-make/pipelined/leaf.rs @@ -0,0 +1,30 @@ +#![crate_type = "rlib"] + +pub static FOO: &str = "this is a static"; + +#[derive(Debug)] +pub struct Plain { + pub a: u32, + pub b: u32, +} + +#[derive(Debug)] +pub struct GenericStruct { + pub a: A, + pub b: Option, +} + +pub fn simple(a: u32, b: u32) -> u32 { + let c = a + b; + println!("simple {} + {} => {}", a, b, c); + c +} + +#[inline] +pub fn inlined(a: u32, b: u32) -> u32 { + a * b +} + +pub fn generic(d: D) { + println!("generically printing {:?}", d); +} diff --git a/src/test/run-make/pipelined/main.rs b/src/test/run-make/pipelined/main.rs new file mode 100644 index 0000000000000..211ecb5672514 --- /dev/null +++ b/src/test/run-make/pipelined/main.rs @@ -0,0 +1,10 @@ +#![crate_type = "bin"] + +fn main() { + middle::do_a_thing(); + + println!("middle::BAR {}", middle::BAR); + + assert_eq!(middle::simple(2, 3), 5); + assert_eq!(middle::inlined(2, 3), 6); +} diff --git a/src/test/run-make/pipelined/middle.rs b/src/test/run-make/pipelined/middle.rs new file mode 100644 index 0000000000000..444ace389b75d --- /dev/null +++ b/src/test/run-make/pipelined/middle.rs @@ -0,0 +1,23 @@ +#![crate_type = "rlib"] + +extern crate leaf; + +pub static BAR: &str = leaf::FOO; + +pub use leaf::simple; +pub use leaf::inlined; + +pub fn do_a_thing() { + let s = leaf::GenericStruct { + a: "hello", + b: Some("world") + }; + + let u = leaf::GenericStruct { + a: leaf::Plain { a: 1, b: 2 }, + b: None + }; + + leaf::generic(s); + leaf::generic(u); +}