diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 0ca634affb4..4122ce18224 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -1,6 +1,7 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. +use std::path::PathBuf; use std::sync::Arc; use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; @@ -19,7 +20,11 @@ use cranelift_object::{ObjectBuilder, ObjectModule}; use crate::global_asm::GlobalAsmConfig; use crate::{prelude::*, BackendConfig}; -struct ModuleCodegenResult(CompiledModule, Option<(WorkProductId, WorkProduct)>); +struct ModuleCodegenResult( + CompiledModule, + Option, + Option<(WorkProductId, WorkProduct)>, +); impl HashStable for ModuleCodegenResult { fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) { @@ -42,11 +47,15 @@ impl OngoingCodegen { let mut modules = vec![]; for module_codegen_result in self.modules { - let ModuleCodegenResult(module, work_product) = module_codegen_result; + let ModuleCodegenResult(module_regular, module_global_asm, work_product) = + module_codegen_result; if let Some((work_product_id, work_product)) = work_product { work_products.insert(work_product_id, work_product); } - modules.push(module); + modules.push(module_regular); + if let Some(module_global_asm) = module_global_asm { + modules.push(module_global_asm); + } } ( @@ -80,6 +89,7 @@ fn emit_module( module: ObjectModule, debug: Option>, unwind_context: UnwindContext, + global_asm_object_file: Option, ) -> ModuleCodegenResult { let mut product = module.finish(); @@ -100,6 +110,12 @@ fn emit_module( let work_product = if backend_config.disable_incr_cache { None + } else if let Some(global_asm_object_file) = &global_asm_object_file { + rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( + tcx.sess, + &name, + &[("o", &tmp_file), ("asm.o", global_asm_object_file)], + ) } else { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( tcx.sess, @@ -109,35 +125,78 @@ fn emit_module( }; ModuleCodegenResult( - CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None }, + CompiledModule { + name: name.clone(), + kind, + object: Some(tmp_file), + dwarf_object: None, + bytecode: None, + }, + global_asm_object_file.map(|global_asm_object_file| CompiledModule { + name: format!("{name}.asm"), + kind, + object: Some(global_asm_object_file), + dwarf_object: None, + bytecode: None, + }), work_product, ) } fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { let work_product = cgu.previous_work_product(tcx); - let obj_out = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); - let source_file = rustc_incremental::in_incr_comp_dir_sess( + let obj_out_regular = + tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); + 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"), ); - if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) { + + if let Err(err) = rustc_fs_util::link_or_copy(&source_file_regular, &obj_out_regular) { tcx.sess.err(&format!( "unable to copy {} to {}: {}", - source_file.display(), - obj_out.display(), + source_file_regular.display(), + obj_out_regular.display(), err )); } + let obj_out_global_asm = + crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm"); + let has_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) + { + tcx.sess.err(&format!( + "unable to copy {} to {}: {}", + source_file_regular.display(), + obj_out_regular.display(), + err + )); + } + true + } else { + false + }; ModuleCodegenResult( CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, - object: Some(obj_out), + object: Some(obj_out_regular), dwarf_object: None, bytecode: None, }, + if has_global_asm { + Some(CompiledModule { + name: cgu.name().to_string(), + kind: ModuleKind::Regular, + object: Some(obj_out_global_asm), + dwarf_object: None, + bytecode: None, + }) + } else { + None + }, Some((cgu.work_product_id(), work_product)), ) } @@ -191,6 +250,15 @@ fn module_codegen( cgu.is_primary(), ); + let global_asm_object_file = match crate::global_asm::compile_global_asm( + &global_asm_config, + cgu.name().as_str(), + &cx.global_asm, + ) { + Ok(global_asm_object_file) => global_asm_object_file, + Err(err) => tcx.sess.fatal(&err), + }; + let debug_context = cx.debug_context; let unwind_context = cx.unwind_context; let codegen_result = tcx.sess.time("write object file", || { @@ -202,18 +270,10 @@ fn module_codegen( module, debug_context, unwind_context, + global_asm_object_file, ) }); - match crate::global_asm::compile_global_asm( - &global_asm_config, - cgu.name().as_str(), - &cx.global_asm, - ) { - Ok(()) => {} - Err(err) => tcx.sess.fatal(&err), - } - codegen_result } @@ -281,7 +341,7 @@ pub(crate) fn run_aot( crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); let allocator_module = if created_alloc_shim { - let ModuleCodegenResult(module, work_product) = emit_module( + let ModuleCodegenResult(module, module_global_asm, work_product) = emit_module( tcx, &backend_config, "allocator_shim".to_string(), @@ -289,7 +349,9 @@ pub(crate) fn run_aot( allocator_module, None, allocator_unwind_context, + None, ); + assert!(module_global_asm.is_none()); if let Some((id, product)) = work_product { work_products.insert(id, product); } diff --git a/src/global_asm.rs b/src/global_asm.rs index 14288e99242..8e711988f81 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -36,7 +36,6 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, pub(crate) struct GlobalAsmConfig { asm_enabled: bool, assembler: PathBuf, - linker: PathBuf, output_filenames: Arc, } @@ -49,7 +48,6 @@ impl GlobalAsmConfig { GlobalAsmConfig { asm_enabled, assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"), - linker: crate::toolchain::get_toolchain_binary(tcx.sess, "ld"), output_filenames: tcx.output_filenames(()).clone(), } } @@ -59,14 +57,14 @@ pub(crate) fn compile_global_asm( config: &GlobalAsmConfig, cgu_name: &str, global_asm: &str, -) -> Result<(), String> { +) -> Result, String> { if global_asm.is_empty() { - return Ok(()); + return Ok(None); } if !config.asm_enabled { if global_asm.contains("__rust_probestack") { - return Ok(()); + return Ok(None); } // FIXME fix linker error on macOS @@ -105,32 +103,10 @@ pub(crate) fn compile_global_asm( return Err(format!("Failed to assemble `{}`", global_asm)); } - // Link the global asm and main object file together - let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main"); - std::fs::rename(&output_object_file, &main_object_file).unwrap(); - let status = Command::new(&config.linker) - .arg("-r") // Create a new object file - .arg("-o") - .arg(output_object_file) - .arg(&main_object_file) - .arg(&global_asm_object_file) - .status() - .unwrap(); - if !status.success() { - return Err(format!( - "Failed to link `{}` and `{}` together", - main_object_file.display(), - global_asm_object_file.display(), - )); - } - - std::fs::remove_file(global_asm_object_file).unwrap(); - std::fs::remove_file(main_object_file).unwrap(); - - Ok(()) + Ok(Some(global_asm_object_file)) } -fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { +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() {