Skip to content

Commit

Permalink
Auto merge of #123221 - pacak:cache_emit, r=fmease,jieyouxu
Browse files Browse the repository at this point in the history
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 #89149
Fixes #88829

Related: https://internals.rust-lang.org/t/interaction-between-incremental-compilation-and-emit/20551
  • Loading branch information
bors committed Apr 7, 2024
2 parents 8f2c255 + 691e953 commit fc1a4c5
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 23 deletions.
18 changes: 17 additions & 1 deletion compiler/rustc_codegen_cranelift/src/driver/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -426,13 +436,17 @@ 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(),
kind: ModuleKind::Regular,
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)),
})
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_gcc/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
))
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
))
}
Expand Down
30 changes: 27 additions & 3 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
{
Expand Down Expand Up @@ -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,
})
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,8 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
object: Some(file_name),
dwarf_object: None,
bytecode: None,
assembly: None,
llvm_ir: None,
}
})
});
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_codegen_ssa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
}

Expand All @@ -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 {
Expand Down
48 changes: 30 additions & 18 deletions src/tools/run-make-support/src/rustc.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down Expand Up @@ -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");
Expand All @@ -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
}
Expand All @@ -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
}
Expand Down
6 changes: 6 additions & 0 deletions tests/run-make/artifact-incr-cache/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#![crate_name = "foo"]

#[inline(never)]
pub fn add(a: u32, b: u32) -> u32 {
a + b
}
25 changes: 25 additions & 0 deletions tests/run-make/artifact-incr-cache/rmake.rs
Original file line number Diff line number Diff line change
@@ -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();
}
}

0 comments on commit fc1a4c5

Please sign in to comment.