mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 05:26:47 +00:00
Prepend temp files with a string per invocation of rustc
This commit is contained in:
parent
effef88ac7
commit
9c372d8940
@ -4407,6 +4407,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"getopts",
|
||||
"libc",
|
||||
"rand 0.9.0",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
|
@ -169,8 +169,11 @@ fn produce_final_output_artifacts(
|
||||
if codegen_results.modules.len() == 1 {
|
||||
// 1) Only one codegen unit. In this case it's no difficulty
|
||||
// to copy `foo.0.x` to `foo.x`.
|
||||
let path =
|
||||
crate_output.temp_path_for_cgu(output_type, &codegen_results.modules[0].name);
|
||||
let path = crate_output.temp_path_for_cgu(
|
||||
output_type,
|
||||
&codegen_results.modules[0].name,
|
||||
sess.invocation_temp.as_deref(),
|
||||
);
|
||||
let output = crate_output.path(output_type);
|
||||
if !output_type.is_text_output() && output.is_tty() {
|
||||
sess.dcx()
|
||||
@ -345,6 +348,7 @@ fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> {
|
||||
|
||||
fn emit_cgu(
|
||||
output_filenames: &OutputFilenames,
|
||||
invocation_temp: Option<&str>,
|
||||
prof: &SelfProfilerRef,
|
||||
name: String,
|
||||
module: UnwindModule<ObjectModule>,
|
||||
@ -360,6 +364,7 @@ fn emit_cgu(
|
||||
|
||||
let module_regular = emit_module(
|
||||
output_filenames,
|
||||
invocation_temp,
|
||||
prof,
|
||||
product.object,
|
||||
ModuleKind::Regular,
|
||||
@ -385,6 +390,7 @@ fn emit_cgu(
|
||||
|
||||
fn emit_module(
|
||||
output_filenames: &OutputFilenames,
|
||||
invocation_temp: Option<&str>,
|
||||
prof: &SelfProfilerRef,
|
||||
mut object: cranelift_object::object::write::Object<'_>,
|
||||
kind: ModuleKind,
|
||||
@ -403,7 +409,7 @@ fn emit_module(
|
||||
object.set_section_data(comment_section, producer, 1);
|
||||
}
|
||||
|
||||
let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name);
|
||||
let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name, invocation_temp);
|
||||
let file = match File::create(&tmp_file) {
|
||||
Ok(file) => file,
|
||||
Err(err) => return Err(format!("error creating object file: {}", err)),
|
||||
@ -443,8 +449,11 @@ fn reuse_workproduct_for_cgu(
|
||||
cgu: &CodegenUnit<'_>,
|
||||
) -> Result<ModuleCodegenResult, String> {
|
||||
let work_product = cgu.previous_work_product(tcx);
|
||||
let obj_out_regular =
|
||||
tcx.output_filenames(()).temp_path_for_cgu(OutputType::Object, cgu.name().as_str());
|
||||
let obj_out_regular = tcx.output_filenames(()).temp_path_for_cgu(
|
||||
OutputType::Object,
|
||||
cgu.name().as_str(),
|
||||
tcx.sess.invocation_temp.as_deref(),
|
||||
);
|
||||
let source_file_regular = rustc_incremental::in_incr_comp_dir_sess(
|
||||
&tcx.sess,
|
||||
&work_product.saved_files.get("o").expect("no saved object file in work product"),
|
||||
@ -589,13 +598,19 @@ fn module_codegen(
|
||||
|
||||
let global_asm_object_file =
|
||||
profiler.generic_activity_with_arg("compile assembly", &*cgu_name).run(|| {
|
||||
crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm)
|
||||
crate::global_asm::compile_global_asm(
|
||||
&global_asm_config,
|
||||
&cgu_name,
|
||||
&cx.global_asm,
|
||||
cx.invocation_temp.as_deref(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let codegen_result =
|
||||
profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| {
|
||||
emit_cgu(
|
||||
&global_asm_config.output_filenames,
|
||||
cx.invocation_temp.as_deref(),
|
||||
&profiler,
|
||||
cgu_name,
|
||||
module,
|
||||
@ -620,8 +635,11 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled
|
||||
.as_str()
|
||||
.to_string();
|
||||
|
||||
let tmp_file =
|
||||
tcx.output_filenames(()).temp_path_for_cgu(OutputType::Metadata, &metadata_cgu_name);
|
||||
let tmp_file = tcx.output_filenames(()).temp_path_for_cgu(
|
||||
OutputType::Metadata,
|
||||
&metadata_cgu_name,
|
||||
tcx.sess.invocation_temp.as_deref(),
|
||||
);
|
||||
|
||||
let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx);
|
||||
let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name);
|
||||
@ -651,6 +669,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> {
|
||||
|
||||
match emit_module(
|
||||
tcx.output_filenames(()),
|
||||
tcx.sess.invocation_temp.as_deref(),
|
||||
&tcx.sess.prof,
|
||||
product.object,
|
||||
ModuleKind::Allocator,
|
||||
|
@ -132,6 +132,7 @@ pub(crate) fn compile_global_asm(
|
||||
config: &GlobalAsmConfig,
|
||||
cgu_name: &str,
|
||||
global_asm: &str,
|
||||
invocation_temp: Option<&str>,
|
||||
) -> Result<Option<PathBuf>, String> {
|
||||
if global_asm.is_empty() {
|
||||
return Ok(None);
|
||||
@ -146,7 +147,7 @@ pub(crate) fn compile_global_asm(
|
||||
global_asm.push('\n');
|
||||
|
||||
let global_asm_object_file = add_file_stem_postfix(
|
||||
config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name),
|
||||
config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp),
|
||||
".asm",
|
||||
);
|
||||
|
||||
|
@ -124,6 +124,7 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
|
||||
/// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
|
||||
struct CodegenCx {
|
||||
output_filenames: Arc<OutputFilenames>,
|
||||
invocation_temp: Option<String>,
|
||||
should_write_ir: bool,
|
||||
global_asm: String,
|
||||
inline_asm_index: usize,
|
||||
@ -142,6 +143,7 @@ impl CodegenCx {
|
||||
};
|
||||
CodegenCx {
|
||||
output_filenames: tcx.output_filenames(()).clone(),
|
||||
invocation_temp: tcx.sess.invocation_temp.clone(),
|
||||
should_write_ir: crate::pretty_clif::should_write_ir(tcx),
|
||||
global_asm: String::new(),
|
||||
inline_asm_index: 0,
|
||||
|
@ -31,8 +31,16 @@ pub(crate) unsafe fn codegen(
|
||||
// TODO(antoyo): remove this environment variable.
|
||||
let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1");
|
||||
|
||||
let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name);
|
||||
let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name);
|
||||
let bc_out = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::Bitcode,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
let obj_out = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::Object,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
|
||||
if config.bitcode_needed() {
|
||||
if fat_lto {
|
||||
@ -113,15 +121,22 @@ pub(crate) unsafe fn codegen(
|
||||
}
|
||||
|
||||
if config.emit_ir {
|
||||
let out =
|
||||
cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name);
|
||||
let out = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::LlvmAssembly,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
std::fs::write(out, "").expect("write file");
|
||||
}
|
||||
|
||||
if config.emit_asm {
|
||||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name);
|
||||
let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name);
|
||||
let path = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::Assembly,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str"));
|
||||
}
|
||||
|
||||
@ -235,6 +250,7 @@ pub(crate) unsafe fn codegen(
|
||||
config.emit_asm,
|
||||
config.emit_ir,
|
||||
&cgcx.output_filenames,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -120,13 +120,17 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar
|
||||
tcx.sess.split_debuginfo(),
|
||||
tcx.sess.opts.unstable_opts.split_dwarf_kind,
|
||||
mod_name,
|
||||
tcx.sess.invocation_temp.as_deref(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let output_obj_file =
|
||||
Some(tcx.output_filenames(()).temp_path_for_cgu(OutputType::Object, mod_name));
|
||||
let output_obj_file = Some(tcx.output_filenames(()).temp_path_for_cgu(
|
||||
OutputType::Object,
|
||||
mod_name,
|
||||
tcx.sess.invocation_temp.as_deref(),
|
||||
));
|
||||
let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file };
|
||||
|
||||
target_machine_factory(
|
||||
@ -330,7 +334,11 @@ pub(crate) fn save_temp_bitcode(
|
||||
return;
|
||||
}
|
||||
let ext = format!("{name}.bc");
|
||||
let path = cgcx.output_filenames.temp_path_ext_for_cgu(&ext, &module.name);
|
||||
let path = cgcx.output_filenames.temp_path_ext_for_cgu(
|
||||
&ext,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
write_bitcode_to_file(module, &path)
|
||||
}
|
||||
|
||||
@ -694,7 +702,11 @@ pub(crate) unsafe fn optimize(
|
||||
let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt);
|
||||
|
||||
if config.emit_no_opt_bc {
|
||||
let out = cgcx.output_filenames.temp_path_ext_for_cgu("no-opt.bc", &module.name);
|
||||
let out = cgcx.output_filenames.temp_path_ext_for_cgu(
|
||||
"no-opt.bc",
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
write_bitcode_to_file(module, &out)
|
||||
}
|
||||
|
||||
@ -739,8 +751,11 @@ pub(crate) unsafe fn optimize(
|
||||
if let Some(thin_lto_buffer) = thin_lto_buffer {
|
||||
let thin_lto_buffer = unsafe { ThinBuffer::from_raw_ptr(thin_lto_buffer) };
|
||||
module.thin_lto_buffer = Some(thin_lto_buffer.data().to_vec());
|
||||
let bc_summary_out =
|
||||
cgcx.output_filenames.temp_path_for_cgu(OutputType::ThinLinkBitcode, &module.name);
|
||||
let bc_summary_out = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::ThinLinkBitcode,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
if config.emit_thin_lto_summary
|
||||
&& let Some(thin_link_bitcode_filename) = bc_summary_out.file_name()
|
||||
{
|
||||
@ -808,8 +823,16 @@ pub(crate) unsafe fn codegen(
|
||||
// copy it to the .o file, and delete the bitcode if it wasn't
|
||||
// otherwise requested.
|
||||
|
||||
let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name);
|
||||
let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name);
|
||||
let bc_out = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::Bitcode,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
let obj_out = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::Object,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
|
||||
if config.bitcode_needed() {
|
||||
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
|
||||
@ -851,8 +874,11 @@ pub(crate) unsafe fn codegen(
|
||||
if config.emit_ir {
|
||||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name);
|
||||
let out =
|
||||
cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name);
|
||||
let out = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::LlvmAssembly,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
let out_c = path_to_c_string(&out);
|
||||
|
||||
extern "C" fn demangle_callback(
|
||||
@ -894,7 +920,11 @@ pub(crate) unsafe fn codegen(
|
||||
if config.emit_asm {
|
||||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name);
|
||||
let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name);
|
||||
let path = cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::Assembly,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
|
||||
// We can't use the same module for asm and object code output,
|
||||
// because that triggers various errors like invalid IR or broken
|
||||
@ -924,7 +954,9 @@ pub(crate) unsafe fn codegen(
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name);
|
||||
|
||||
let dwo_out = cgcx.output_filenames.temp_path_dwo_for_cgu(&module.name);
|
||||
let dwo_out = cgcx
|
||||
.output_filenames
|
||||
.temp_path_dwo_for_cgu(&module.name, cgcx.invocation_temp.as_deref());
|
||||
let dwo_out = match (cgcx.split_debuginfo, cgcx.split_dwarf_kind) {
|
||||
// Don't change how DWARF is emitted when disabled.
|
||||
(SplitDebuginfo::Off, _) => None,
|
||||
@ -989,6 +1021,7 @@ pub(crate) unsafe fn codegen(
|
||||
config.emit_asm,
|
||||
config.emit_ir,
|
||||
&cgcx.output_filenames,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -911,6 +911,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
|
||||
tcx.sess.split_debuginfo(),
|
||||
tcx.sess.opts.unstable_opts.split_dwarf_kind,
|
||||
codegen_unit_name,
|
||||
tcx.sess.invocation_temp.as_deref(),
|
||||
) {
|
||||
// We get a path relative to the working directory from split_dwarf_path
|
||||
Some(tcx.sess.source_map().path_mapping().to_real_filename(f))
|
||||
|
@ -112,7 +112,12 @@ pub fn link_binary(
|
||||
codegen_results.crate_info.local_crate_name,
|
||||
);
|
||||
let crate_name = format!("{}", codegen_results.crate_info.local_crate_name);
|
||||
let out_filename = output.file_for_writing(outputs, OutputType::Exe, &crate_name);
|
||||
let out_filename = output.file_for_writing(
|
||||
outputs,
|
||||
OutputType::Exe,
|
||||
&crate_name,
|
||||
sess.invocation_temp.as_deref(),
|
||||
);
|
||||
match crate_type {
|
||||
CrateType::Rlib => {
|
||||
let _timer = sess.timer("link_rlib");
|
||||
|
@ -307,13 +307,17 @@ impl TargetMachineFactoryConfig {
|
||||
cgcx.split_debuginfo,
|
||||
cgcx.split_dwarf_kind,
|
||||
module_name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let output_obj_file =
|
||||
Some(cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, module_name));
|
||||
let output_obj_file = Some(cgcx.output_filenames.temp_path_for_cgu(
|
||||
OutputType::Object,
|
||||
module_name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
));
|
||||
TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }
|
||||
}
|
||||
}
|
||||
@ -344,6 +348,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
|
||||
pub crate_types: Vec<CrateType>,
|
||||
pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>,
|
||||
pub output_filenames: Arc<OutputFilenames>,
|
||||
pub invocation_temp: Option<String>,
|
||||
pub regular_module_config: Arc<ModuleConfig>,
|
||||
pub metadata_module_config: Arc<ModuleConfig>,
|
||||
pub allocator_module_config: Arc<ModuleConfig>,
|
||||
@ -582,7 +587,11 @@ fn produce_final_output_artifacts(
|
||||
if let [module] = &compiled_modules.modules[..] {
|
||||
// 1) Only one codegen unit. In this case it's no difficulty
|
||||
// to copy `foo.0.x` to `foo.x`.
|
||||
let path = crate_output.temp_path_for_cgu(output_type, &module.name);
|
||||
let path = crate_output.temp_path_for_cgu(
|
||||
output_type,
|
||||
&module.name,
|
||||
sess.invocation_temp.as_deref(),
|
||||
);
|
||||
let output = crate_output.path(output_type);
|
||||
if !output_type.is_text_output() && output.is_tty() {
|
||||
sess.dcx()
|
||||
@ -959,7 +968,12 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
||||
module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| {
|
||||
let dwarf_obj_out = cgcx
|
||||
.output_filenames
|
||||
.split_dwarf_path(cgcx.split_debuginfo, cgcx.split_dwarf_kind, &module.name)
|
||||
.split_dwarf_path(
|
||||
cgcx.split_debuginfo,
|
||||
cgcx.split_dwarf_kind,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
)
|
||||
.expect(
|
||||
"saved dwarf object in work product but `split_dwarf_path` returned `None`",
|
||||
);
|
||||
@ -969,7 +983,11 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
||||
let mut 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_for_cgu(output_type, &module.name);
|
||||
let output_path = cgcx.output_filenames.temp_path_for_cgu(
|
||||
output_type,
|
||||
&module.name,
|
||||
cgcx.invocation_temp.as_deref(),
|
||||
);
|
||||
load_from_incr_comp_dir(output_path, &saved_file)
|
||||
} else {
|
||||
None
|
||||
@ -1214,6 +1232,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||
split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
|
||||
parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
|
||||
pointer_size: tcx.data_layout.pointer_size,
|
||||
invocation_temp: sess.invocation_temp.clone(),
|
||||
};
|
||||
|
||||
// This is the "main loop" of parallel work happening for parallel codegen.
|
||||
|
@ -640,9 +640,11 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||
let metadata_cgu_name =
|
||||
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
|
||||
tcx.sess.time("write_compressed_metadata", || {
|
||||
let file_name = tcx
|
||||
.output_filenames(())
|
||||
.temp_path_for_cgu(OutputType::Metadata, &metadata_cgu_name);
|
||||
let file_name = tcx.output_filenames(()).temp_path_for_cgu(
|
||||
OutputType::Metadata,
|
||||
&metadata_cgu_name,
|
||||
tcx.sess.invocation_temp.as_deref(),
|
||||
);
|
||||
let data = create_compressed_metadata_file(
|
||||
tcx.sess,
|
||||
&metadata,
|
||||
|
@ -105,14 +105,19 @@ impl<M> ModuleCodegen<M> {
|
||||
emit_asm: bool,
|
||||
emit_ir: bool,
|
||||
outputs: &OutputFilenames,
|
||||
invocation_temp: Option<&str>,
|
||||
) -> CompiledModule {
|
||||
let object = emit_obj.then(|| outputs.temp_path_for_cgu(OutputType::Object, &self.name));
|
||||
let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo_for_cgu(&self.name));
|
||||
let bytecode = emit_bc.then(|| outputs.temp_path_for_cgu(OutputType::Bitcode, &self.name));
|
||||
let assembly =
|
||||
emit_asm.then(|| outputs.temp_path_for_cgu(OutputType::Assembly, &self.name));
|
||||
let llvm_ir =
|
||||
emit_ir.then(|| outputs.temp_path_for_cgu(OutputType::LlvmAssembly, &self.name));
|
||||
let object = emit_obj
|
||||
.then(|| outputs.temp_path_for_cgu(OutputType::Object, &self.name, invocation_temp));
|
||||
let dwarf_object =
|
||||
emit_dwarf_obj.then(|| outputs.temp_path_dwo_for_cgu(&self.name, invocation_temp));
|
||||
let bytecode = emit_bc
|
||||
.then(|| outputs.temp_path_for_cgu(OutputType::Bitcode, &self.name, invocation_temp));
|
||||
let assembly = emit_asm
|
||||
.then(|| outputs.temp_path_for_cgu(OutputType::Assembly, &self.name, invocation_temp));
|
||||
let llvm_ir = emit_ir.then(|| {
|
||||
outputs.temp_path_for_cgu(OutputType::LlvmAssembly, &self.name, invocation_temp)
|
||||
});
|
||||
|
||||
CompiledModule {
|
||||
name: self.name.clone(),
|
||||
|
@ -800,6 +800,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
|
||||
sess.opts.cg.metadata.clone(),
|
||||
sess.cfg_version,
|
||||
);
|
||||
|
||||
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
|
||||
|
||||
let dep_type = DepsType { dep_names: rustc_query_impl::dep_kind_names() };
|
||||
|
@ -7,6 +7,7 @@ edition = "2024"
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
getopts = "0.2"
|
||||
rand = "0.9.0"
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
|
@ -1016,10 +1016,13 @@ impl OutFileName {
|
||||
outputs: &OutputFilenames,
|
||||
flavor: OutputType,
|
||||
codegen_unit_name: &str,
|
||||
invocation_temp: Option<&str>,
|
||||
) -> PathBuf {
|
||||
match *self {
|
||||
OutFileName::Real(ref path) => path.clone(),
|
||||
OutFileName::Stdout => outputs.temp_path_for_cgu(flavor, codegen_unit_name),
|
||||
OutFileName::Stdout => {
|
||||
outputs.temp_path_for_cgu(flavor, codegen_unit_name, invocation_temp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1094,21 +1097,41 @@ impl OutputFilenames {
|
||||
/// Gets the path where a compilation artifact of the given type for the
|
||||
/// given codegen unit should be placed on disk. If codegen_unit_name is
|
||||
/// None, a path distinct from those of any codegen unit will be generated.
|
||||
pub fn temp_path_for_cgu(&self, flavor: OutputType, codegen_unit_name: &str) -> PathBuf {
|
||||
pub fn temp_path_for_cgu(
|
||||
&self,
|
||||
flavor: OutputType,
|
||||
codegen_unit_name: &str,
|
||||
invocation_temp: Option<&str>,
|
||||
) -> PathBuf {
|
||||
let extension = flavor.extension();
|
||||
self.temp_path_ext_for_cgu(extension, codegen_unit_name)
|
||||
self.temp_path_ext_for_cgu(extension, codegen_unit_name, invocation_temp)
|
||||
}
|
||||
|
||||
/// Like `temp_path`, but specifically for dwarf objects.
|
||||
pub fn temp_path_dwo_for_cgu(&self, codegen_unit_name: &str) -> PathBuf {
|
||||
self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name)
|
||||
pub fn temp_path_dwo_for_cgu(
|
||||
&self,
|
||||
codegen_unit_name: &str,
|
||||
invocation_temp: Option<&str>,
|
||||
) -> PathBuf {
|
||||
self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp)
|
||||
}
|
||||
|
||||
/// Like `temp_path`, but also supports things where there is no corresponding
|
||||
/// OutputType, like noopt-bitcode or lto-bitcode.
|
||||
pub fn temp_path_ext_for_cgu(&self, ext: &str, codegen_unit_name: &str) -> PathBuf {
|
||||
pub fn temp_path_ext_for_cgu(
|
||||
&self,
|
||||
ext: &str,
|
||||
codegen_unit_name: &str,
|
||||
invocation_temp: Option<&str>,
|
||||
) -> PathBuf {
|
||||
let mut extension = codegen_unit_name.to_string();
|
||||
|
||||
// Append `.{invocation_temp}` to ensure temporary files are unique.
|
||||
if let Some(rng) = invocation_temp {
|
||||
extension.push('.');
|
||||
extension.push_str(rng);
|
||||
}
|
||||
|
||||
// FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty.
|
||||
// Append `.rcgu.{ext}`.
|
||||
if !ext.is_empty() {
|
||||
@ -1144,9 +1167,10 @@ impl OutputFilenames {
|
||||
split_debuginfo_kind: SplitDebuginfo,
|
||||
split_dwarf_kind: SplitDwarfKind,
|
||||
cgu_name: &str,
|
||||
invocation_temp: Option<&str>,
|
||||
) -> Option<PathBuf> {
|
||||
let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name);
|
||||
let dwo_out = self.temp_path_dwo_for_cgu(cgu_name);
|
||||
let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp);
|
||||
let dwo_out = self.temp_path_dwo_for_cgu(cgu_name, invocation_temp);
|
||||
match (split_debuginfo_kind, split_dwarf_kind) {
|
||||
(SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None,
|
||||
// Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes
|
||||
|
@ -6,6 +6,8 @@ use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::{env, fmt, io};
|
||||
|
||||
use rand::{RngCore, rng};
|
||||
use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
|
||||
use rustc_data_structures::flock;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
||||
use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
|
||||
@ -203,6 +205,14 @@ pub struct Session {
|
||||
|
||||
target_filesearch: FileSearch,
|
||||
host_filesearch: FileSearch,
|
||||
|
||||
/// A random string generated per invocation of rustc.
|
||||
///
|
||||
/// This is prepended to all temporary files so that they do not collide
|
||||
/// during concurrent invocations of rustc, or past invocations that were
|
||||
/// preserved with a flag like `-C save-temps`, since these files may be
|
||||
/// hard linked.
|
||||
pub invocation_temp: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
@ -1117,6 +1127,12 @@ pub fn build_session(
|
||||
let target_filesearch =
|
||||
filesearch::FileSearch::new(&sopts.search_paths, &target_tlib_path, &target);
|
||||
let host_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &host_tlib_path, &host);
|
||||
|
||||
let invocation_temp = sopts
|
||||
.incremental
|
||||
.as_ref()
|
||||
.map(|_| rng().next_u32().to_base_fixed_len(CASE_INSENSITIVE).to_string());
|
||||
|
||||
let sess = Session {
|
||||
target,
|
||||
host,
|
||||
@ -1140,6 +1156,7 @@ pub fn build_session(
|
||||
expanded_args,
|
||||
target_filesearch,
|
||||
host_filesearch,
|
||||
invocation_temp,
|
||||
};
|
||||
|
||||
validate_commandline_args_with_session_available(&sess);
|
||||
|
32
tests/run-make/dirty-incr-due-to-hard-link/rmake.rs
Normal file
32
tests/run-make/dirty-incr-due-to-hard-link/rmake.rs
Normal file
@ -0,0 +1,32 @@
|
||||
//@ only-x86_64-unknown-linux-gnu
|
||||
|
||||
// Regression test for the incremental bug in <https://github.com/rust-lang/rust/issues/139407>.
|
||||
//
|
||||
// A detailed explanation is described in <https://github.com/rust-lang/rust/pull/139453>,
|
||||
// however the gist of the issue is that hard-linking temporary files can interact strangely
|
||||
// across incremental sessions that are not finalized due to errors originating from the
|
||||
// codegen backend.
|
||||
|
||||
use run_make_support::{run, rustc};
|
||||
|
||||
fn main() {
|
||||
let mk_rustc = || {
|
||||
let mut rustc = rustc();
|
||||
rustc.input("test.rs").incremental("incr").arg("-Csave-temps").output("test");
|
||||
rustc
|
||||
};
|
||||
|
||||
// Revision 1
|
||||
mk_rustc().cfg("rpass1").run();
|
||||
|
||||
run("test");
|
||||
|
||||
// Revision 2
|
||||
mk_rustc().cfg("cfail2").run_fail();
|
||||
// Expected to fail.
|
||||
|
||||
// Revision 3
|
||||
mk_rustc().cfg("rpass3").run();
|
||||
|
||||
run("test");
|
||||
}
|
31
tests/run-make/dirty-incr-due-to-hard-link/test.rs
Normal file
31
tests/run-make/dirty-incr-due-to-hard-link/test.rs
Normal file
@ -0,0 +1,31 @@
|
||||
#[inline(never)]
|
||||
#[cfg(any(rpass1, rpass3))]
|
||||
fn a() -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(any(cfail2))]
|
||||
fn a() -> i32 {
|
||||
1
|
||||
}
|
||||
|
||||
fn main() {
|
||||
evil::evil();
|
||||
assert_eq!(a(), 0);
|
||||
}
|
||||
|
||||
mod evil {
|
||||
#[cfg(any(rpass1, rpass3))]
|
||||
pub fn evil() {
|
||||
unsafe {
|
||||
std::arch::asm!("/* */");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(cfail2))]
|
||||
pub fn evil() {
|
||||
unsafe {
|
||||
std::arch::asm!("missing");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user