Skip to content

Commit 38dffeb

Browse files
committed
Move metadata writing earlier.
The commit moves metadata writing from `link_binary` to `encode_metadata` (and renames the latter as `encode_and_write_metadata`). This is at the very start of code generation.
1 parent 3da5d4a commit 38dffeb

File tree

4 files changed

+48
-34
lines changed

4 files changed

+48
-34
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,6 +2802,7 @@ dependencies = [
28022802
"rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
28032803
"rustc_allocator 0.0.0",
28042804
"rustc_borrowck 0.0.0",
2805+
"rustc_codegen_ssa 0.0.0",
28052806
"rustc_codegen_utils 0.0.0",
28062807
"rustc_data_structures 0.0.0",
28072808
"rustc_errors 0.0.0",
@@ -2821,6 +2822,7 @@ dependencies = [
28212822
"syntax 0.0.0",
28222823
"syntax_ext 0.0.0",
28232824
"syntax_pos 0.0.0",
2825+
"tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
28242826
]
28252827

28262828
[[package]]

src/librustc_codegen_ssa/back/link.rs

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc::session::config::{
77
};
88
use rustc::session::search_paths::PathKind;
99
use rustc::middle::dependency_format::Linkage;
10-
use rustc::middle::cstore::{LibSource, NativeLibrary, NativeLibraryKind};
10+
use rustc::middle::cstore::{EncodedMetadata, LibSource, NativeLibrary, NativeLibraryKind};
1111
use rustc::util::common::{time, time_ext};
1212
use rustc::hir::def_id::CrateNum;
1313
use rustc_data_structures::fx::FxHashSet;
@@ -50,9 +50,9 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
5050
outputs: &OutputFilenames,
5151
crate_name: &str,
5252
target_cpu: &str) {
53+
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
5354
for &crate_type in sess.crate_types.borrow().iter() {
5455
// Ignore executable crates if we have -Z no-codegen, as they will error.
55-
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
5656
if (sess.opts.debugging_opts.no_codegen || !sess.opts.output_types.should_codegen()) &&
5757
!output_metadata &&
5858
crate_type == config::CrateType::Executable {
@@ -68,29 +68,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
6868
check_file_is_writeable(obj, sess);
6969
}
7070

71-
if outputs.outputs.contains_key(&OutputType::Metadata) {
72-
let out_filename = filename_for_metadata(sess, crate_name, outputs);
73-
// To avoid races with another rustc process scanning the output directory,
74-
// we need to write the file somewhere else and atomically move it to its
75-
// final destination, with a `fs::rename` call. In order for the rename to
76-
// always succeed, the temporary file needs to be on the same filesystem,
77-
// which is why we create it inside the output directory specifically.
78-
let metadata_tmpdir = TempFileBuilder::new()
79-
.prefix("rmeta")
80-
.tempdir_in(out_filename.parent().unwrap())
81-
.unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
82-
let metadata = emit_metadata(sess, codegen_results, &metadata_tmpdir);
83-
match fs::rename(&metadata, &out_filename) {
84-
Ok(_) => {
85-
if sess.opts.debugging_opts.emit_directives {
86-
sess.parse_sess.span_diagnostic.maybe_emit_json_directive(
87-
format!("metadata file written: {}", out_filename.display()));
88-
}
89-
}
90-
Err(e) => sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)),
91-
}
92-
}
93-
9471
let tmpdir = TempFileBuilder::new().prefix("rustc").tempdir().unwrap_or_else(|err|
9572
sess.fatal(&format!("couldn't create a temp dir: {}", err)));
9673

@@ -248,13 +225,13 @@ pub fn each_linked_rlib(sess: &Session,
248225
/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
249226
/// directory being searched for `extern crate` (observing an incomplete file).
250227
/// The returned path is the temporary file containing the complete metadata.
251-
fn emit_metadata<'a>(
228+
pub fn emit_metadata<'a>(
252229
sess: &'a Session,
253-
codegen_results: &CodegenResults,
230+
metadata: &EncodedMetadata,
254231
tmpdir: &TempDir
255232
) -> PathBuf {
256233
let out_filename = tmpdir.path().join(METADATA_FILENAME);
257-
let result = fs::write(&out_filename, &codegen_results.metadata.raw_data);
234+
let result = fs::write(&out_filename, &metadata.raw_data);
258235

259236
if let Err(e) = result {
260237
sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
@@ -338,7 +315,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
338315
RlibFlavor::Normal => {
339316
// Instead of putting the metadata in an object file section, rlibs
340317
// contain the metadata in a separate file.
341-
ab.add_file(&emit_metadata(sess, codegen_results, tmpdir));
318+
ab.add_file(&emit_metadata(sess, &codegen_results.metadata, tmpdir));
342319

343320
// For LTO purposes, the bytecode of this library is also inserted
344321
// into the archive.

src/librustc_interface/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ rustc_borrowck = { path = "../librustc_borrowck" }
2424
rustc_incremental = { path = "../librustc_incremental" }
2525
rustc_traits = { path = "../librustc_traits" }
2626
rustc_data_structures = { path = "../librustc_data_structures" }
27+
rustc_codegen_ssa = { path = "../librustc_codegen_ssa" }
2728
rustc_codegen_utils = { path = "../librustc_codegen_utils" }
2829
rustc_metadata = { path = "../librustc_metadata" }
2930
rustc_mir = { path = "../librustc_mir" }
@@ -34,3 +35,4 @@ rustc_errors = { path = "../librustc_errors" }
3435
rustc_plugin = { path = "../librustc_plugin" }
3536
rustc_privacy = { path = "../librustc_privacy" }
3637
rustc_resolve = { path = "../librustc_resolve" }
38+
tempfile = "3.0.5"

src/librustc_interface/passes.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType
2020
use rustc::session::search_paths::PathKind;
2121
use rustc_allocator as allocator;
2222
use rustc_borrowck as borrowck;
23+
use rustc_codegen_ssa::back::link::emit_metadata;
2324
use rustc_codegen_utils::codegen_backend::CodegenBackend;
25+
use rustc_codegen_utils::link::filename_for_metadata;
2426
use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
2527
use rustc_data_structures::fingerprint::Fingerprint;
2628
use rustc_data_structures::stable_hasher::StableHasher;
@@ -50,6 +52,7 @@ use syntax_pos::{FileName, hygiene};
5052
use syntax_ext;
5153

5254
use serialize::json;
55+
use tempfile::Builder as TempFileBuilder;
5356

5457
use std::any::Any;
5558
use std::env;
@@ -999,7 +1002,10 @@ fn analysis<'tcx>(
9991002
Ok(())
10001003
}
10011004

1002-
fn encode_metadata<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> (middle::cstore::EncodedMetadata, bool) {
1005+
fn encode_and_write_metadata<'tcx>(
1006+
tcx: TyCtxt<'_, 'tcx, 'tcx>,
1007+
outputs: &OutputFilenames,
1008+
) -> (middle::cstore::EncodedMetadata, bool) {
10031009
#[derive(PartialEq, Eq, PartialOrd, Ord)]
10041010
enum MetadataKind {
10051011
None,
@@ -1020,14 +1026,41 @@ fn encode_metadata<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> (middle::cstore::Encode
10201026
}
10211027
}).max().unwrap_or(MetadataKind::None);
10221028

1023-
let need_metadata_module = metadata_kind == MetadataKind::Compressed;
1024-
10251029
let metadata = match metadata_kind {
10261030
MetadataKind::None => middle::cstore::EncodedMetadata::new(),
10271031
MetadataKind::Uncompressed |
10281032
MetadataKind::Compressed => tcx.encode_metadata(),
10291033
};
10301034

1035+
let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata);
1036+
if need_metadata_file {
1037+
let crate_name = &tcx.crate_name(LOCAL_CRATE).as_str();
1038+
let out_filename = filename_for_metadata(tcx.sess, crate_name, outputs);
1039+
// To avoid races with another rustc process scanning the output directory,
1040+
// we need to write the file somewhere else and atomically move it to its
1041+
// final destination, with an `fs::rename` call. In order for the rename to
1042+
// always succeed, the temporary file needs to be on the same filesystem,
1043+
// which is why we create it inside the output directory specifically.
1044+
let metadata_tmpdir = TempFileBuilder::new()
1045+
.prefix("rmeta")
1046+
.tempdir_in(out_filename.parent().unwrap())
1047+
.unwrap_or_else(|err| {
1048+
tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err))
1049+
});
1050+
let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir);
1051+
match std::fs::rename(&metadata_filename, &out_filename) {
1052+
Ok(_) => {
1053+
if tcx.sess.opts.debugging_opts.emit_directives {
1054+
tcx.sess.parse_sess.span_diagnostic.maybe_emit_json_directive(
1055+
format!("metadata file written: {}", out_filename.display()));
1056+
}
1057+
}
1058+
Err(e) => tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)),
1059+
}
1060+
}
1061+
1062+
let need_metadata_module = metadata_kind == MetadataKind::Compressed;
1063+
10311064
(metadata, need_metadata_module)
10321065
}
10331066

@@ -1048,8 +1081,8 @@ pub fn start_codegen<'tcx>(
10481081
middle::dependency_format::calculate(tcx)
10491082
});
10501083

1051-
let (metadata, need_metadata_module) = time(tcx.sess, "metadata encoding", || {
1052-
encode_metadata(tcx)
1084+
let (metadata, need_metadata_module) = time(tcx.sess, "metadata encoding and writing", || {
1085+
encode_and_write_metadata(tcx, outputs)
10531086
});
10541087

10551088
tcx.sess.profiler(|p| p.start_activity("codegen crate"));

0 commit comments

Comments
 (0)