diff options
| author | bors <bors@rust-lang.org> | 2024-04-07 10:46:50 +0000 | 
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-04-07 10:46:50 +0000 | 
| commit | fc1a4c5cc9308c4b5980c64a73fd344a59c10601 (patch) | |
| tree | 5c57656ec61dea95a81c63b10fa7dc47d0e542fe | |
| parent | 8f2c255ae03c524323a52d7003ac176beaa3ea74 (diff) | |
| parent | 691e953da6aa5dc21d999fb81f0f13ce1816828f (diff) | |
| download | rust-fc1a4c5cc9308c4b5980c64a73fd344a59c10601.tar.gz rust-fc1a4c5cc9308c4b5980c64a73fd344a59c10601.zip  | |
Auto merge of #123221 - pacak:cache_emit, r=fmease,jieyouxu
Save/restore more items in cache with incremental compilation
Right now they don't play very well together, consider a simple example:
```
$ export RUSTFLAGS="--emit asm"
$ cargo new --lib foo
     Created library `foo` package
$ cargo build -q
$ touch src/lib.rs
$ cargo build
error: could not copy
  "/path/to/foo/target/debug/deps/foo-e307cc7fa7b6d64f.4qbzn9k8mosu50a5.rcgu.s"
  to "/path/to/foo/target/debug/deps/foo-e307cc7fa7b6d64f.s":
  No such file or directory (os error 2)
```
Touch triggers the rebuild, incremental compilation detects no changes (yay) and everything explodes while trying to copy files were they should go.
This pull request fixes it by copying and restoring more files in the incremental compilation cache
Fixes https://github.com/rust-lang/rust/issues/89149
Fixes https://github.com/rust-lang/rust/issues/88829
Related: https://internals.rust-lang.org/t/interaction-between-incremental-compilation-and-emit/20551
| -rw-r--r-- | compiler/rustc_codegen_cranelift/src/driver/aot.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_codegen_gcc/src/back/write.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/back/write.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/write.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/base.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/lib.rs | 17 | ||||
| -rw-r--r-- | src/tools/run-make-support/src/rustc.rs | 48 | ||||
| -rw-r--r-- | tests/run-make/artifact-incr-cache/lib.rs | 6 | ||||
| -rw-r--r-- | tests/run-make/artifact-incr-cache/rmake.rs | 25 | 
9 files changed, 127 insertions, 23 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 75268341a4f..e8c96486041 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -341,6 +341,8 @@ fn emit_cgu( object: Some(global_asm_object_file), dwarf_object: None, bytecode: None, + assembly: None, + llvm_ir: None, }), existing_work_product: None, }) @@ -378,7 +380,15 @@ fn emit_module( prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); - Ok(CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None }) + Ok(CompiledModule { + name, + kind, + object: Some(tmp_file), + dwarf_object: None, + bytecode: None, + assembly: None, + llvm_ir: None, + }) } fn reuse_workproduct_for_cgu( @@ -426,6 +436,8 @@ fn reuse_workproduct_for_cgu( object: Some(obj_out_regular), dwarf_object: None, bytecode: None, + assembly: None, + llvm_ir: None, }, module_global_asm: has_global_asm.then(|| CompiledModule { name: cgu.name().to_string(), @@ -433,6 +445,8 @@ fn reuse_workproduct_for_cgu( object: Some(obj_out_global_asm), dwarf_object: None, bytecode: None, + assembly: None, + llvm_ir: None, }), existing_work_product: Some((cgu.work_product_id(), work_product)), }) @@ -678,6 +692,8 @@ pub(crate) fn run_aot( object: Some(tmp_file), dwarf_object: None, bytecode: None, + assembly: None, + llvm_ir: None, }) } else { None diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs index 76a619a1af7..3ea5be1ee56 100644 --- a/compiler/rustc_codegen_gcc/src/back/write.rs +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -158,6 +158,8 @@ pub(crate) unsafe fn codegen( config.emit_obj != EmitObj::None, cgcx.target_can_use_split_dwarf && cgcx.split_debuginfo == SplitDebuginfo::Unpacked, config.emit_bc, + config.emit_asm, + config.emit_ir, &cgcx.output_filenames, )) } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 68ba8cbf7b7..49f9d7ddab6 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -880,6 +880,8 @@ pub(crate) unsafe fn codegen( config.emit_obj != EmitObj::None, dwarf_object_emitted, config.emit_bc, + config.emit_asm, + config.emit_ir, &cgcx.output_filenames, )) } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index b7bcaac3b18..e7f692144ff 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -528,12 +528,20 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { let mut files = Vec::new(); if let Some(object_file_path) = &module.object { - files.push(("o", object_file_path.as_path())); + files.push((OutputType::Object.extension(), object_file_path.as_path())); } if let Some(dwarf_object_file_path) = &module.dwarf_object { files.push(("dwo", dwarf_object_file_path.as_path())); } - + if let Some(path) = &module.assembly { + files.push((OutputType::Assembly.extension(), path.as_path())); + } + if let Some(path) = &module.llvm_ir { + files.push((OutputType::LlvmAssembly.extension(), path.as_path())); + } + if let Some(path) = &module.bytecode { + files.push((OutputType::Bitcode.extension(), path.as_path())); + } if let Some((id, product)) = copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, files.as_slice()) { @@ -937,12 +945,28 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file) }); + let load_from_incr_cache = |perform, output_type: OutputType| { + if perform { + let saved_file = module.source.saved_files.get(output_type.extension())?; + let output_path = cgcx.output_filenames.temp_path(output_type, Some(&module.name)); + load_from_incr_comp_dir(output_path, &saved_file) + } else { + None + } + }; + + let assembly = load_from_incr_cache(module_config.emit_asm, OutputType::Assembly); + let llvm_ir = load_from_incr_cache(module_config.emit_ir, OutputType::LlvmAssembly); + let bytecode = load_from_incr_cache(module_config.emit_bc, OutputType::Bitcode); + WorkItemResult::Finished(CompiledModule { name: module.name, kind: ModuleKind::Regular, object, dwarf_object, - bytecode: None, + bytecode, + assembly, + llvm_ir, }) } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 410b5d27c57..c4c16ee7311 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -656,6 +656,8 @@ pub fn codegen_crate<B: ExtraBackendMethods>( object: Some(file_name), dwarf_object: None, bytecode: None, + assembly: None, + llvm_ir: None, } }) }); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 9be8dcf166d..80fe7e0bb78 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -79,13 +79,26 @@ impl<M> ModuleCodegen<M> { emit_obj: bool, emit_dwarf_obj: bool, emit_bc: bool, + emit_asm: bool, + emit_ir: bool, outputs: &OutputFilenames, ) -> CompiledModule { let object = emit_obj.then(|| outputs.temp_path(OutputType::Object, Some(&self.name))); let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo(Some(&self.name))); let bytecode = emit_bc.then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name))); + let assembly = emit_asm.then(|| outputs.temp_path(OutputType::Assembly, Some(&self.name))); + let llvm_ir = + emit_ir.then(|| outputs.temp_path(OutputType::LlvmAssembly, Some(&self.name))); - CompiledModule { name: self.name.clone(), kind: self.kind, object, dwarf_object, bytecode } + CompiledModule { + name: self.name.clone(), + kind: self.kind, + object, + dwarf_object, + bytecode, + assembly, + llvm_ir, + } } } @@ -96,6 +109,8 @@ pub struct CompiledModule { pub object: Option<PathBuf>, pub dwarf_object: Option<PathBuf>, pub bytecode: Option<PathBuf>, + pub assembly: Option<PathBuf>, // --emit=asm + pub llvm_ir: Option<PathBuf>, // --emit=llvm-ir, llvm-bc is in bytecode } pub struct CachedModuleCodegen { diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index 50ff0d26bbb..217da36ccc7 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -1,5 +1,5 @@ use std::env; -use std::ffi::OsStr; +use std::ffi::{OsStr, OsString}; use std::path::Path; use std::process::{Command, Output}; @@ -86,6 +86,33 @@ impl Rustc { self } + /// Specify number of codegen units + pub fn codegen_units(&mut self, units: usize) -> &mut Self { + self.cmd.arg(format!("-Ccodegen-units={units}")); + self + } + + /// Specify directory path used for incremental cache + pub fn incremental<P: AsRef<Path>>(&mut self, path: P) -> &mut Self { + let mut arg = OsString::new(); + arg.push("-Cincremental="); + arg.push(path.as_ref()); + self.cmd.arg(&arg); + self + } + + /// Specify error format to use + pub fn error_format(&mut self, format: &str) -> &mut Self { + self.cmd.arg(format!("--error-format={format}")); + self + } + + /// Specify json messages printed by the compiler + pub fn json(&mut self, items: &str) -> &mut Self { + self.cmd.arg(format!("--json={items}")); + self + } + /// Specify target triple. pub fn target(&mut self, target: &str) -> &mut Self { assert!(!target.contains(char::is_whitespace), "target triple cannot contain spaces"); @@ -94,13 +121,7 @@ impl Rustc { } /// Generic command argument provider. Use `.arg("-Zname")` over `.arg("-Z").arg("arg")`. - /// This method will panic if a plain `-Z` or `-C` is passed, or if `-Z <name>` or `-C <name>` - /// is passed (note the space). - pub fn arg(&mut self, arg: &str) -> &mut Self { - assert!( - !(["-Z", "-C"].contains(&arg) || arg.starts_with("-Z ") || arg.starts_with("-C ")), - "use `-Zarg` or `-Carg` over split `-Z` `arg` or `-C` `arg`" - ); + pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self { self.cmd.arg(arg); self } @@ -120,16 +141,7 @@ impl Rustc { } /// Generic command arguments provider. Use `.arg("-Zname")` over `.arg("-Z").arg("arg")`. - /// This method will panic if a plain `-Z` or `-C` is passed, or if `-Z <name>` or `-C <name>` - /// is passed (note the space). - pub fn args(&mut self, args: &[&str]) -> &mut Self { - for arg in args { - assert!( - !(["-Z", "-C"].contains(&arg) || arg.starts_with("-Z ") || arg.starts_with("-C ")), - "use `-Zarg` or `-Carg` over split `-Z` `arg` or `-C` `arg`" - ); - } - + pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut Self { self.cmd.args(args); self } diff --git a/tests/run-make/artifact-incr-cache/lib.rs b/tests/run-make/artifact-incr-cache/lib.rs new file mode 100644 index 00000000000..fa4048594e3 --- /dev/null +++ b/tests/run-make/artifact-incr-cache/lib.rs @@ -0,0 +1,6 @@ +#![crate_name = "foo"] + +#[inline(never)] +pub fn add(a: u32, b: u32) -> u32 { + a + b +} diff --git a/tests/run-make/artifact-incr-cache/rmake.rs b/tests/run-make/artifact-incr-cache/rmake.rs new file mode 100644 index 00000000000..bb651368081 --- /dev/null +++ b/tests/run-make/artifact-incr-cache/rmake.rs @@ -0,0 +1,25 @@ +// rustc should be able to emit required files (asm, llvm-*, etc) during incremental +// compilation on the first pass by running the code gen as well as on subsequent runs - +// extracting them from the cache +// +// Fixes: rust-lang/rust#89149 +// Fixes: rust-lang/rust#88829 +// Also see discussion at +// <https://internals.rust-lang.org/t/interaction-between-incremental-compilation-and-emit/20551> + +extern crate run_make_support; + +use run_make_support::{rustc, tmp_dir}; + +fn main() { + let inc_dir = tmp_dir(); + + for _ in 0..=1 { + rustc() + .input("lib.rs") + .crate_type("lib") + .emit("obj,asm,dep-info,link,mir,llvm-ir,llvm-bc") + .incremental(&inc_dir) + .run(); + } +}  | 
