Rollup merge of #97058 - bjorn3:multi_artifact_work_products, r=nagisa

Various refactors to the incr comp workproduct handling

This is the result of me looking into adding support for having multiple object files for a single codegen unit to incr comp. This is necessary to support inline assembly in cg_clif without requiring partial linking which is not supported on Windows and seems to fail on macOS for some reason. Cg_clif uses an external assembler to handle inline asm and thus produces one object file with regular functions and one object file containing compiled inline asm for each codegen unit which uses inline asm. Current incr comp can't handle this. This PR doesn't yet add support for this, but it makes it easier to do so.
This commit is contained in:
Dylan DPC 2022-06-07 11:41:06 +02:00 committed by GitHub
commit ab1027ad0f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 75 additions and 102 deletions

View file

@ -66,11 +66,7 @@ fn emit_module(
let work_product = if backend_config.disable_incr_cache { let work_product = if backend_config.disable_incr_cache {
None None
} else { } else {
rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(tcx.sess, &name, &tmp_file)
tcx.sess,
&name,
&Some(tmp_file.clone()),
)
}; };
ModuleCodegenResult( ModuleCodegenResult(
@ -84,21 +80,16 @@ fn reuse_workproduct_for_cgu(
cgu: &CodegenUnit<'_>, cgu: &CodegenUnit<'_>,
work_products: &mut FxHashMap<WorkProductId, WorkProduct>, work_products: &mut FxHashMap<WorkProductId, WorkProduct>,
) -> CompiledModule { ) -> CompiledModule {
let mut object = None; let work_product = cgu.previous_work_product(tcx);
let work_product = cgu.work_product(tcx); let obj_out = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str()));
if let Some(saved_file) = &work_product.saved_file { let source_file = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, &work_product.saved_file);
let obj_out = if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) {
tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); tcx.sess.err(&format!(
object = Some(obj_out.clone()); "unable to copy {} to {}: {}",
let source_file = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, &saved_file); source_file.display(),
if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) { obj_out.display(),
tcx.sess.err(&format!( err
"unable to copy {} to {}: {}", ));
source_file.display(),
obj_out.display(),
err
));
}
} }
work_products.insert(cgu.work_product_id(), work_product); work_products.insert(cgu.work_product_id(), work_product);
@ -106,7 +97,7 @@ fn reuse_workproduct_for_cgu(
CompiledModule { CompiledModule {
name: cgu.name().to_string(), name: cgu.name().to_string(),
kind: ModuleKind::Regular, kind: ModuleKind::Regular,
object, object: Some(obj_out),
dwarf_object: None, dwarf_object: None,
bytecode: None, bytecode: None,
} }

View file

@ -494,12 +494,12 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir"); let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir");
for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
let path = module.object.as_ref().cloned(); if let Some(path) = &module.object {
if let Some((id, product)) =
if let Some((id, product)) = copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, path)
copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, &path) {
{ work_products.insert(id, product);
work_products.insert(id, product); }
} }
} }
@ -853,35 +853,31 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
module: CachedModuleCodegen, module: CachedModuleCodegen,
module_config: &ModuleConfig, module_config: &ModuleConfig,
) -> WorkItemResult<B> { ) -> WorkItemResult<B> {
let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); assert!(module_config.emit_obj != EmitObj::None);
let mut object = None;
if let Some(saved_file) = module.source.saved_file {
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name));
object = Some(obj_out.clone());
let source_file = in_incr_comp_dir(&incr_comp_session_dir, &saved_file);
debug!(
"copying pre-existing module `{}` from {:?} to {}",
module.name,
source_file,
obj_out.display()
);
if let Err(err) = link_or_copy(&source_file, &obj_out) {
let diag_handler = cgcx.create_diag_handler();
diag_handler.err(&format!(
"unable to copy {} to {}: {}",
source_file.display(),
obj_out.display(),
err
));
}
}
assert_eq!(object.is_some(), module_config.emit_obj != EmitObj::None); let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name));
let source_file = in_incr_comp_dir(&incr_comp_session_dir, &module.source.saved_file);
debug!(
"copying pre-existing module `{}` from {:?} to {}",
module.name,
source_file,
obj_out.display()
);
if let Err(err) = link_or_copy(&source_file, &obj_out) {
let diag_handler = cgcx.create_diag_handler();
diag_handler.err(&format!(
"unable to copy {} to {}: {}",
source_file.display(),
obj_out.display(),
err
));
}
WorkItemResult::Compiled(CompiledModule { WorkItemResult::Compiled(CompiledModule {
name: module.name, name: module.name,
kind: ModuleKind::Regular, kind: ModuleKind::Regular,
object, object: Some(obj_out),
dwarf_object: None, dwarf_object: None,
bytecode: None, bytecode: None,
}) })

View file

@ -716,7 +716,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
&ongoing_codegen.coordinator_send, &ongoing_codegen.coordinator_send,
CachedModuleCodegen { CachedModuleCodegen {
name: cgu.name().to_string(), name: cgu.name().to_string(),
source: cgu.work_product(tcx), source: cgu.previous_work_product(tcx),
}, },
); );
true true
@ -727,7 +727,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
&ongoing_codegen.coordinator_send, &ongoing_codegen.coordinator_send,
CachedModuleCodegen { CachedModuleCodegen {
name: cgu.name().to_string(), name: cgu.name().to_string(),
source: cgu.work_product(tcx), source: cgu.previous_work_product(tcx),
}, },
); );
true true

View file

@ -162,18 +162,16 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
for swp in work_products { for swp in work_products {
let mut all_files_exist = true; let mut all_files_exist = true;
if let Some(ref file_name) = swp.work_product.saved_file { let path = in_incr_comp_dir_sess(sess, &swp.work_product.saved_file);
let path = in_incr_comp_dir_sess(sess, file_name); if !path.exists() {
if !path.exists() { all_files_exist = false;
all_files_exist = false;
if sess.opts.debugging_opts.incremental_info { if sess.opts.debugging_opts.incremental_info {
eprintln!( eprintln!(
"incremental: could not find file for work \ "incremental: could not find file for work \
product: {}", product: {}",
path.display() path.display()
); );
}
} }
} }

View file

@ -107,11 +107,7 @@ pub fn save_work_product_index(
for (id, wp) in previous_work_products.iter() { for (id, wp) in previous_work_products.iter() {
if !new_work_products.contains_key(id) { if !new_work_products.contains_key(id) {
work_product::delete_workproduct_files(sess, wp); work_product::delete_workproduct_files(sess, wp);
debug_assert!( debug_assert!(!in_incr_comp_dir_sess(sess, &wp.saved_file).exists());
wp.saved_file.as_ref().map_or(true, |file_name| {
!in_incr_comp_dir_sess(sess, &file_name).exists()
})
);
} }
} }
@ -119,8 +115,7 @@ pub fn save_work_product_index(
debug_assert!({ debug_assert!({
new_work_products new_work_products
.iter() .iter()
.flat_map(|(_, wp)| wp.saved_file.iter()) .map(|(_, wp)| in_incr_comp_dir_sess(sess, &wp.saved_file))
.map(|name| in_incr_comp_dir_sess(sess, name))
.all(|path| path.exists()) .all(|path| path.exists())
}); });
} }

View file

@ -7,34 +7,30 @@ use rustc_fs_util::link_or_copy;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_session::Session; use rustc_session::Session;
use std::fs as std_fs; use std::fs as std_fs;
use std::path::PathBuf; use std::path::Path;
/// Copies a CGU work product to the incremental compilation directory, so next compilation can find and reuse it. /// Copies a CGU work product to the incremental compilation directory, so next compilation can find and reuse it.
pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
sess: &Session, sess: &Session,
cgu_name: &str, cgu_name: &str,
path: &Option<PathBuf>, path: &Path,
) -> Option<(WorkProductId, WorkProduct)> { ) -> Option<(WorkProductId, WorkProduct)> {
debug!("copy_cgu_workproduct_to_incr_comp_cache_dir({:?},{:?})", cgu_name, path); debug!("copy_cgu_workproduct_to_incr_comp_cache_dir({:?},{:?})", cgu_name, path);
sess.opts.incremental.as_ref()?; sess.opts.incremental.as_ref()?;
let saved_file = if let Some(path) = path { let file_name = format!("{}.o", cgu_name);
let file_name = format!("{}.o", cgu_name); let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); let saved_file = match link_or_copy(path, &path_in_incr_dir) {
match link_or_copy(path, &path_in_incr_dir) { Ok(_) => file_name,
Ok(_) => Some(file_name), Err(err) => {
Err(err) => { sess.warn(&format!(
sess.warn(&format!( "error copying object file `{}` to incremental directory as `{}`: {}",
"error copying object file `{}` to incremental directory as `{}`: {}", path.display(),
path.display(), path_in_incr_dir.display(),
path_in_incr_dir.display(), err
err ));
)); return None;
return None;
}
} }
} else {
None
}; };
let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_file }; let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_file };
@ -45,17 +41,15 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
/// Removes files for a given work product. /// Removes files for a given work product.
pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) { pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
if let Some(ref file_name) = work_product.saved_file { let path = in_incr_comp_dir_sess(sess, &work_product.saved_file);
let path = in_incr_comp_dir_sess(sess, file_name); match std_fs::remove_file(&path) {
match std_fs::remove_file(&path) { Ok(()) => {}
Ok(()) => {} Err(err) => {
Err(err) => { sess.warn(&format!(
sess.warn(&format!( "file-system error deleting outdated file `{}`: {}",
"file-system error deleting outdated file `{}`: {}", path.display(),
path.display(), err
err ));
));
}
} }
} }
} }

View file

@ -336,7 +336,7 @@ impl<'tcx> CodegenUnit<'tcx> {
WorkProductId::from_cgu_name(self.name().as_str()) WorkProductId::from_cgu_name(self.name().as_str())
} }
pub fn work_product(&self, tcx: TyCtxt<'_>) -> WorkProduct { pub fn previous_work_product(&self, tcx: TyCtxt<'_>) -> WorkProduct {
let work_product_id = self.work_product_id(); let work_product_id = self.work_product_id();
tcx.dep_graph tcx.dep_graph
.previous_work_product(&work_product_id) .previous_work_product(&work_product_id)

View file

@ -164,7 +164,6 @@ pub struct WorkProductId {
impl WorkProductId { impl WorkProductId {
pub fn from_cgu_name(cgu_name: &str) -> WorkProductId { pub fn from_cgu_name(cgu_name: &str) -> WorkProductId {
let mut hasher = StableHasher::new(); let mut hasher = StableHasher::new();
cgu_name.len().hash(&mut hasher);
cgu_name.hash(&mut hasher); cgu_name.hash(&mut hasher);
WorkProductId { hash: hasher.finish() } WorkProductId { hash: hasher.finish() }
} }

View file

@ -887,7 +887,7 @@ impl<K: DepKind> DepGraph<K> {
pub struct WorkProduct { pub struct WorkProduct {
pub cgu_name: String, pub cgu_name: String,
/// Saved file associated with this CGU. /// Saved file associated with this CGU.
pub saved_file: Option<String>, pub saved_file: String,
} }
// Index type for `DepNodeData`'s edges. // Index type for `DepNodeData`'s edges.