From e731b4e5f9da236a0525e6a815c4261aa835b334 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 27 May 2026 15:09:42 +0000 Subject: [PATCH] Allow two object files for a single CGU in CompiledModule cg_clif needs this as it passes inline assembly to an external assembler, producing a separate object file. Currently it emits multiple CompiledModules, but this is not compatible with using the codegen coordinator of cg_ssa. --- .../rustc_codegen_cranelift/src/driver/aot.rs | 66 +++++++------------ .../rustc_codegen_cranelift/src/global_asm.rs | 18 +---- compiler/rustc_codegen_ssa/src/back/link.rs | 57 ++++++++++++---- compiler/rustc_codegen_ssa/src/back/write.rs | 15 +++++ compiler/rustc_codegen_ssa/src/lib.rs | 2 + 5 files changed, 85 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 3781ad7b3b83f..323fec06bcc58 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -35,8 +35,7 @@ fn disable_incr_cache() -> bool { } struct ModuleCodegenResult { - module_regular: CompiledModule, - module_global_asm: Option, + module: CompiledModule, existing_work_product: Option<(WorkProductId, WorkProduct)>, } @@ -80,29 +79,25 @@ impl OngoingCodegen { Ok(module_codegen_result) => module_codegen_result, Err(err) => sess.dcx().fatal(err), }; - let ModuleCodegenResult { module_regular, module_global_asm, existing_work_product } = - module_codegen_result; + let ModuleCodegenResult { module, existing_work_product } = module_codegen_result; if let Some((work_product_id, work_product)) = existing_work_product { work_products.insert(work_product_id, work_product); } else { let work_product = if disable_incr_cache { None - } else if let Some(module_global_asm) = &module_global_asm { + } else if let Some(global_asm_object) = &module.global_asm_object { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( sess, - &module_regular.name, - &[ - ("o", module_regular.object.as_ref().unwrap()), - ("asm.o", module_global_asm.object.as_ref().unwrap()), - ], + &module.name, + &[("o", module.object.as_ref().unwrap()), ("asm.o", global_asm_object)], &[], ) } else { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( sess, - &module_regular.name, - &[("o", module_regular.object.as_ref().unwrap())], + &module.name, + &[("o", module.object.as_ref().unwrap())], &[], ) }; @@ -111,10 +106,7 @@ impl OngoingCodegen { } } - modules.push(module_regular); - if let Some(module_global_asm) = module_global_asm { - modules.push(module_global_asm); - } + modules.push(module); } self.concurrency_limiter.finished(); @@ -163,29 +155,17 @@ fn emit_cgu( debug.emit(&mut product); } - let module_regular = emit_module( + let module = emit_module( output_filenames, prof, product.object, ModuleKind::Regular, name.clone(), + global_asm_object_file, producer, )?; - Ok(ModuleCodegenResult { - module_regular, - module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule { - name: format!("{name}.asm"), - kind: ModuleKind::Regular, - object: Some(global_asm_object_file), - dwarf_object: None, - bytecode: None, - assembly: None, - llvm_ir: None, - links_from_incr_cache: Vec::new(), - }), - existing_work_product: None, - }) + Ok(ModuleCodegenResult { module, existing_work_product: None }) } fn emit_module( @@ -194,6 +174,7 @@ fn emit_module( mut object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, name: String, + global_asm_object: Option, producer_str: &str, ) -> Result { if object.format() == cranelift_object::object::BinaryFormat::Elf { @@ -235,6 +216,7 @@ fn emit_module( name, kind, object: Some(tmp_file), + global_asm_object, dwarf_object: None, bytecode: None, assembly: None, @@ -265,7 +247,7 @@ fn reuse_workproduct_for_cgu( } let obj_out_global_asm = - crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm"); + tcx.output_filenames(()).temp_path_ext_for_cgu("asm.o", cgu.name().as_str()); let source_file_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(tcx.sess, asm_o); if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm) @@ -283,26 +265,21 @@ fn reuse_workproduct_for_cgu( }; Ok(ModuleCodegenResult { - module_regular: CompiledModule { + module: CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, object: Some(obj_out_regular), + global_asm_object: source_file_global_asm.as_ref().map(|_| obj_out_global_asm), dwarf_object: None, bytecode: None, assembly: None, llvm_ir: None, - links_from_incr_cache: vec![source_file_regular], + links_from_incr_cache: if let Some(source_file_global_asm) = source_file_global_asm { + vec![source_file_regular, source_file_global_asm] + } else { + vec![source_file_regular] + }, }, - module_global_asm: source_file_global_asm.map(|source_file| 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, - links_from_incr_cache: vec![source_file], - }), existing_work_product: Some((cgu.work_product_id(), work_product)), }) } @@ -447,6 +424,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option { product.object, ModuleKind::Allocator, "allocator_shim".to_owned(), + None, &crate::debuginfo::producer(tcx.sess), ) { Ok(allocator_module) => Some(allocator_module), diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 0c5f4136a32d6..ee7e6732e6a77 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, }; -use rustc_session::config::{OutputFilenames, OutputType}; +use rustc_session::config::OutputFilenames; use rustc_target::asm::InlineAsmArch; use crate::prelude::*; @@ -198,10 +198,7 @@ pub(crate) fn compile_global_asm( .join("\n"); global_asm.push('\n'); - let global_asm_object_file = add_file_stem_postfix( - config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name), - ".asm", - ); + let global_asm_object_file = config.output_filenames.temp_path_ext_for_cgu("asm.o", cgu_name); // Assemble `global_asm` if option_env!("CG_CLIF_FORCE_GNU_AS").is_some() { @@ -271,14 +268,3 @@ pub(crate) fn compile_global_asm( Ok(Some(global_asm_object_file)) } - -pub(crate) fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { - let mut new_filename = path.file_stem().unwrap().to_owned(); - new_filename.push(postfix); - if let Some(extension) = path.extension() { - new_filename.push("."); - new_filename.push(extension); - } - path.set_file_name(new_filename); - path -} diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index d2c82280ad2ab..0152030ea875b 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -98,8 +98,13 @@ pub fn link_binary( } sess.time("link_binary_check_files_are_writeable", || { - for obj in compiled_modules.modules.iter().filter_map(|m| m.object.as_ref()) { - check_file_is_writeable(obj, sess); + for m in &compiled_modules.modules { + if let Some(obj) = &m.object { + check_file_is_writeable(obj, sess); + } + if let Some(obj) = &m.global_asm_object { + check_file_is_writeable(obj, sess); + } } }); @@ -202,6 +207,10 @@ pub fn link_binary( ensure_removed(sess.dcx(), obj); } + if !preserve_objects && let Some(ref obj) = module.global_asm_object { + ensure_removed(sess.dcx(), obj); + } + if !preserve_dwarf_objects && let Some(ref dwo_obj) = module.dwarf_object { ensure_removed(sess.dcx(), dwo_obj); } @@ -307,6 +316,7 @@ fn link_rlib<'a>( .modules .iter() .filter_map(|m| m.object.as_ref()) + .chain(compiled_modules.modules.iter().filter_map(|m| m.global_asm_object.as_ref())) .map(|obj| obj.file_name().unwrap().to_str().unwrap().to_string()) .collect(); @@ -352,6 +362,10 @@ fn link_rlib<'a>( ab.add_file(obj); } + if let Some(obj) = m.global_asm_object.as_ref() { + ab.add_file(obj); + } + if let Some(dwarf_obj) = m.dwarf_object.as_ref() { ab.add_file(dwarf_obj); } @@ -360,9 +374,13 @@ fn link_rlib<'a>( match flavor { RlibFlavor::Normal => {} RlibFlavor::StaticlibBase => { - let obj = compiled_modules.allocator_module.as_ref().and_then(|m| m.object.as_ref()); - if let Some(obj) = obj { - ab.add_file(obj); + if let Some(m) = &compiled_modules.allocator_module { + if let Some(obj) = &m.object { + ab.add_file(obj); + } + if let Some(obj) = &m.global_asm_object { + ab.add_file(obj); + } } } } @@ -632,8 +650,13 @@ fn link_dwarf_object( // Input objs contain .o/.dwo files from the current crate. match sess.opts.unstable_opts.split_dwarf_kind { SplitDwarfKind::Single => { - for input_obj in compiled_modules.modules.iter().filter_map(|m| m.object.as_ref()) { - package.add_input_object(input_obj)?; + for m in &compiled_modules.modules { + if let Some(input_obj) = &m.object { + package.add_input_object(input_obj)?; + } + if let Some(input_obj) = &m.global_asm_object { + package.add_input_object(input_obj)?; + } } } SplitDwarfKind::Split => { @@ -2243,8 +2266,13 @@ fn add_linked_symbol_object( /// Add object files containing code from the current crate. fn add_local_crate_regular_objects(cmd: &mut dyn Linker, compiled_modules: &CompiledModules) { - for obj in compiled_modules.modules.iter().filter_map(|m| m.object.as_ref()) { - cmd.add_object(obj); + for m in &compiled_modules.modules { + if let Some(obj) = &m.object { + cmd.add_object(obj); + } + if let Some(obj) = &m.global_asm_object { + cmd.add_object(obj); + } } } @@ -2255,10 +2283,13 @@ fn add_local_crate_allocator_objects( crate_info: &CrateInfo, crate_type: CrateType, ) { - if needs_allocator_shim_for_linking(&crate_info.dependency_formats, crate_type) { - if let Some(obj) = - compiled_modules.allocator_module.as_ref().and_then(|m| m.object.as_ref()) - { + if needs_allocator_shim_for_linking(&crate_info.dependency_formats, crate_type) + && let Some(m) = &compiled_modules.allocator_module + { + if let Some(obj) = &m.object { + cmd.add_object(obj); + } + if let Some(obj) = &m.global_asm_object { cmd.add_object(obj); } } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 7b22ac231df1c..54693d0a69527 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -474,6 +474,9 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( if let Some(object_file_path) = &module.object { files.push((OutputType::Object.extension(), object_file_path.as_path())); } + if let Some(global_asm_object_file_path) = &module.global_asm_object { + files.push(("asm.o", global_asm_object_file_path.as_path())); + } if let Some(dwarf_object_file_path) = &module.dwarf_object { files.push(("dwo", dwarf_object_file_path.as_path())); } @@ -620,6 +623,10 @@ pub fn produce_final_output_artifacts( ensure_removed(sess.dcx(), path); } + if let Some(ref path) = module.global_asm_object { + ensure_removed(sess.dcx(), path); + } + if let Some(ref path) = module.dwarf_object { ensure_removed(sess.dcx(), path); } @@ -924,6 +931,13 @@ fn execute_copy_from_cache_work_item( 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); let object = load_from_incr_cache(should_emit_obj, OutputType::Object); + let global_asm_object = + if should_emit_obj && let Some(saved_file) = module.source.saved_files.get("asm.o") { + let output_path = cgcx.output_filenames.temp_path_ext_for_cgu("asm.o", &module.name); + load_from_incr_comp_dir(output_path, &saved_file) + } else { + None + }; if should_emit_obj && object.is_none() { dcx.emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name }) } @@ -933,6 +947,7 @@ fn execute_copy_from_cache_work_item( kind: ModuleKind::Regular, name: module.name, object, + global_asm_object, dwarf_object, bytecode, assembly, diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index c7446bd784b40..560cbe98f7497 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -109,6 +109,7 @@ impl ModuleCodegen { name: self.name, kind: self.kind, object, + global_asm_object: None, dwarf_object, bytecode, assembly, @@ -123,6 +124,7 @@ pub struct CompiledModule { pub name: String, pub kind: ModuleKind, pub object: Option, + pub global_asm_object: Option, pub dwarf_object: Option, pub bytecode: Option, pub assembly: Option, // --emit=asm