From f360e7243bf5c12d86b7dd185bdf448387e3d43b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 11 Apr 2025 10:35:24 -0400 Subject: [PATCH 1/7] Remove -fuse-linker-plugin since we do LTO before the linker is invoked --- src/back/write.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/back/write.rs b/src/back/write.rs index 16c895322e8..26ce62e11e3 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -169,12 +169,6 @@ pub(crate) unsafe fn codegen( if fat_lto { context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); - - // NOTE: without -fuse-linker-plugin, we get the following error: - // lto1: internal compiler error: decompressed stream: Destination buffer is too small - // TODO(antoyo): since we do not do LTO when the linker is invoked anymore, perhaps - // the following flag is not necessary anymore. - context.add_driver_option("-fuse-linker-plugin"); } context.add_driver_option("-Wl,-r"); From e85346ee7388fd3289a5440b374872dbf6f1f7ee Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 11 Apr 2025 20:23:15 -0400 Subject: [PATCH 2/7] Support symbols_below_threshold --- build_system/build_sysroot/Cargo.toml | 2 +- src/back/lto.rs | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/build_system/build_sysroot/Cargo.toml b/build_system/build_sysroot/Cargo.toml index 24152070e64..d445a184d86 100644 --- a/build_system/build_sysroot/Cargo.toml +++ b/build_system/build_sysroot/Cargo.toml @@ -35,4 +35,4 @@ codegen-units = 10000 [profile.release] debug = "limited" -#lto = "fat" # TODO(antoyo): re-enable when the failing LTO tests regarding proc-macros are fixed. +lto = "fat" # TODO(antoyo): re-enable when the failing LTO tests regarding proc-macros are fixed. diff --git a/src/back/lto.rs b/src/back/lto.rs index e5221c7da31..0d4726c7af9 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -50,8 +50,7 @@ pub fn crate_type_allows_lto(crate_type: CrateType) -> bool { } struct LtoData { - // TODO(antoyo): use symbols_below_threshold. - //symbols_below_threshold: Vec, + symbols_below_threshold: Vec, upstream_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, } @@ -156,7 +155,11 @@ fn prepare_lto( } } - Ok(LtoData { upstream_modules, tmp_path }) + Ok(LtoData { + upstream_modules, + symbols_below_threshold, + tmp_path, + }) } fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { @@ -175,8 +178,8 @@ pub(crate) fn run_fat( let dcx = cgcx.create_dcx(); let dcx = dcx.handle(); let lto_data = prepare_lto(cgcx, dcx)?; - /*let symbols_below_threshold = - lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ + let symbols_below_threshold = + lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>(); fat_lto( cgcx, dcx, @@ -184,7 +187,7 @@ pub(crate) fn run_fat( cached_modules, lto_data.upstream_modules, lto_data.tmp_path, - //<o_data.symbols_below_threshold, + <o_data.symbols_below_threshold, ) } @@ -195,7 +198,7 @@ fn fat_lto( cached_modules: Vec<(SerializedModule, WorkProduct)>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, - //symbols_below_threshold: &[String], + symbols_below_threshold: &[String], ) -> Result, FatalError> { let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module"); info!("going for a fat lto"); @@ -312,6 +315,11 @@ fn fat_lto( } save_temp_bitcode(cgcx, &module, "lto.input"); + for symbol in symbols_below_threshold { + println!("Internalize {}", symbol); + // TODO: Create a function that is always_inline and that calls the symbol here (e.g. + // main)? + } // Internalize everything below threshold to help strip out more modules and such. /*unsafe { let ptr = symbols_below_threshold.as_ptr(); From d01e7d1669a61fb9e7fb3b02675c0f35886d1c8e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 13 Apr 2025 07:11:27 -0400 Subject: [PATCH 3/7] WIP: Fix undefined symbol errors --- src/back/lto.rs | 23 +++++++++++++++++++---- src/back/write.rs | 7 +++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 0d4726c7af9..8ce1f59f0f5 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -21,7 +21,7 @@ use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::sync::Arc; -use gccjit::{Context, OutputKind}; +use gccjit::{Context, FnAttribute, FunctionType, GlobalKind, OutputKind}; use object::read::archive::ArchiveFile; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::symbol_export; @@ -178,8 +178,6 @@ pub(crate) fn run_fat( let dcx = cgcx.create_dcx(); let dcx = dcx.handle(); let lto_data = prepare_lto(cgcx, dcx)?; - let symbols_below_threshold = - lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>(); fat_lto( cgcx, dcx, @@ -315,11 +313,28 @@ fn fat_lto( } save_temp_bitcode(cgcx, &module, "lto.input"); + let int_type = module.module_llvm.context.new_type::(); for symbol in symbols_below_threshold { - println!("Internalize {}", symbol); + println!("*** Keeping symbol: {}", symbol); + module.module_llvm.context.new_global(None, GlobalKind::Imported, int_type, symbol); // TODO: Create a function that is always_inline and that calls the symbol here (e.g. // main)? } + let void_type = module.module_llvm.context.new_type::<()>(); + let main_func = module.module_llvm.context.new_function(None, FunctionType::Extern, void_type, &[], "main", false); + main_func.add_attribute(FnAttribute::Used); + + // NOTE: look at the code from 64b30d344ce54f8ee496cb3590b4c7cf3cb30447 to see previous + // attemps. + let func = module.module_llvm.context.new_function(None, FunctionType::Exported, void_type, &[], "__my_call_main", false); + func.add_attribute(FnAttribute::AlwaysInline); + func.add_attribute(FnAttribute::Inline); + func.add_attribute(FnAttribute::Used); + let block = func.new_block("start"); + let call = module.module_llvm.context.new_call(None, main_func, &[]); + block.add_eval(None, call); + block.end_with_void_return(None); + // Internalize everything below threshold to help strip out more modules and such. /*unsafe { let ptr = symbols_below_threshold.as_ptr(); diff --git a/src/back/write.rs b/src/back/write.rs index 26ce62e11e3..df3ba14c261 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -169,6 +169,11 @@ pub(crate) unsafe fn codegen( if fat_lto { context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); + + // FIXME: the problem is probably that the code is only in GIMPLE IR while + // we would want to get the optimized asm done from LTO. + // ===> But we call "gcc -x lto" later, so that should be asm and not + // GIMPLE IR. } context.add_driver_option("-Wl,-r"); @@ -206,6 +211,8 @@ pub(crate) unsafe fn codegen( context.add_driver_option("lto"); add_pic_option(&context, module.module_llvm.relocation_model); context.add_driver_option(lto_path); + // TODO TODO: inspect the resulting file to see if it contains the GIMPLE IR or + // the asm. context.compile_to_file(OutputKind::ObjectFile, path); } else { From d84c07413fcd2e68d5c8fca35b3f928ff822316f Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 6 May 2025 09:17:13 -0400 Subject: [PATCH 4/7] WIP: Working state for having the test program to compile with LTO This requires having the following line commented in libgccjit: ADD_ARG ("-fno-use-linker-plugin"); And this also requires having the sysroot compiled with fat LTO. --- src/back/lto.rs | 28 +++++++++++++++++++++++----- src/back/write.rs | 18 ++++++++++++++++++ src/declare.rs | 4 ++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 8ce1f59f0f5..536aa5e1528 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -280,6 +280,7 @@ fn fat_lto( context.set_optimization_level(to_gcc_opt_level(config.opt_level)); context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); + //context.add_command_line_option("-fno-use-linker-plugin"); context.compile_to_file(OutputKind::ObjectFile, path); let buffer = ModuleBuffer::new(PathBuf::from(path)); let llmod_id = CString::new(&module.name[..]).unwrap(); @@ -314,6 +315,20 @@ fn fat_lto( save_temp_bitcode(cgcx, &module, "lto.input"); let int_type = module.module_llvm.context.new_type::(); + /* + * TODO: Preserve the symbols via a linker script instead? + * TODO TODO: use the symbols in inline asm to keep them? + * ===> This seems to work and is easy. + * + * FIXME: main is not genarated in GIMPLE IR; it is generated as asm. + * ===> seems now fixed since I commented this line in libgccjit: + * ADD_ARG ("-fno-use-linker-plugin"); + * FIXME: it seems "make install" doesn't copy liblto_plugin.so. + * ===> seems now fixed after a rebuild. + * + * TODO TODO TODO: add -fno-use-linker-plugin because: + * This option is enabled by default when LTO support in GCC is enabled and GCC was configured for use with a linker supporting plugins (GNU ld 2.21 or newer or gold). + */ for symbol in symbols_below_threshold { println!("*** Keeping symbol: {}", symbol); module.module_llvm.context.new_global(None, GlobalKind::Imported, int_type, symbol); @@ -322,17 +337,20 @@ fn fat_lto( } let void_type = module.module_llvm.context.new_type::<()>(); let main_func = module.module_llvm.context.new_function(None, FunctionType::Extern, void_type, &[], "main", false); - main_func.add_attribute(FnAttribute::Used); + //main_func.add_attribute(FnAttribute::Used); // NOTE: look at the code from 64b30d344ce54f8ee496cb3590b4c7cf3cb30447 to see previous // attemps. let func = module.module_llvm.context.new_function(None, FunctionType::Exported, void_type, &[], "__my_call_main", false); - func.add_attribute(FnAttribute::AlwaysInline); - func.add_attribute(FnAttribute::Inline); + //func.add_attribute(FnAttribute::AlwaysInline); + //func.add_attribute(FnAttribute::Inline); func.add_attribute(FnAttribute::Used); let block = func.new_block("start"); - let call = module.module_llvm.context.new_call(None, main_func, &[]); - block.add_eval(None, call); + let main_func_address = main_func.get_address(None); + /*let asm = block.add_extended_asm(None, ""); + asm.add_input_operand(None, "X", main_func_address);*/ + //let call = module.module_llvm.context.new_call(None, main_func, &[]); + //block.add_eval(None, call); block.end_with_void_return(None); // Internalize everything below threshold to help strip out more modules and such. diff --git a/src/back/write.rs b/src/back/write.rs index df3ba14c261..9f4194fefe9 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -57,6 +57,9 @@ pub(crate) unsafe fn codegen( ); }*/ + // TODO: make this work to make it easier to debug GCC-related issue within + // rustc_codegen_gcc: + //context.add_driver_option("-wrapper gdb,--args"); if config.emit_bc || config.emit_obj == EmitObj::Bitcode { let _timer = cgcx.prof.generic_activity_with_arg( "GCC_module_codegen_emit_bitcode", @@ -64,6 +67,7 @@ pub(crate) unsafe fn codegen( ); context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); + //context.add_command_line_option("-fno-use-linker-plugin"); // TODO(antoyo): remove since we don't want fat objects when it is for Bitcode only. context.add_command_line_option("-ffat-lto-objects"); context.compile_to_file( @@ -82,6 +86,7 @@ pub(crate) unsafe fn codegen( context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); + //context.add_command_line_option("-fno-use-linker-plugin"); context.add_command_line_option("-ffat-lto-objects"); // TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument). context.compile_to_file( @@ -169,6 +174,14 @@ pub(crate) unsafe fn codegen( if fat_lto { context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); + //context.add_command_line_option("-ffat-lto-objects"); + //context.add_command_line_option("-fno-use-linker-plugin"); + + // FIXME FIXME FIXME: + // /usr/bin/ld: warning: incremental linking of LTO and non-LTO objects; using -flinker-output=nolto-rel which will bypass whole program optimization + // ====> So I'm probably missing -flto somewhere. + + println!("**** Adding -flto to {:?}", obj_out.to_str().expect("path to str")); // FIXME: the problem is probably that the code is only in GIMPLE IR while // we would want to get the optimized asm done from LTO. @@ -180,6 +193,7 @@ pub(crate) unsafe fn codegen( // NOTE: we need -nostdlib, otherwise, we get the following error: // /usr/bin/ld: cannot find -lgcc_s: No such file or directory context.add_driver_option("-nostdlib"); + //context.add_driver_option("-v"); let path = obj_out.to_str().expect("path to str"); @@ -193,9 +207,12 @@ pub(crate) unsafe fn codegen( // // This option is to mute it to make the UI tests pass with LTO enabled. context.add_driver_option("-Wno-lto-type-mismatch"); + //context.add_driver_option("-v"); // NOTE: this doesn't actually generate an executable. With the above // flags, it combines the .o files together in another .o. + println!("Lto path: {:?}", lto_path); context.compile_to_file(OutputKind::Executable, <o_path); + println!("****************************************************************************************************"); let context = Context::default(); if cgcx.target_arch == "x86" || cgcx.target_arch == "x86_64" { @@ -209,6 +226,7 @@ pub(crate) unsafe fn codegen( // needs to be at the very beginning. context.add_driver_option("-x"); context.add_driver_option("lto"); + //context.add_driver_option("-v"); add_pic_option(&context, module.module_llvm.relocation_model); context.add_driver_option(lto_path); // TODO TODO: inspect the resulting file to see if it contains the GIMPLE IR or diff --git a/src/declare.rs b/src/declare.rs index c1ca3eb849e..f2101fed7eb 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -189,6 +189,10 @@ fn declare_raw_fn<'gcc>( .collect(); #[cfg(not(feature = "master"))] let name = &mangle_name(name); + if name == "main" { + //cx.context.add_driver_option("-v"); + println!("**** Main function in {}", cx.codegen_unit.name()); + } let func = cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, name, variadic); #[cfg(feature = "master")] From 78ee4f1a11a27831f597e4bab17e65bf9200435d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 6 May 2025 17:24:07 -0400 Subject: [PATCH 5/7] Some more debugging --- src/back/lto.rs | 5 ++++- src/back/write.rs | 14 +++++++++++--- src/gcc_util.rs | 2 ++ src/lib.rs | 8 ++++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 536aa5e1528..e11b1a99299 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -280,7 +280,8 @@ fn fat_lto( context.set_optimization_level(to_gcc_opt_level(config.opt_level)); context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); - //context.add_command_line_option("-fno-use-linker-plugin"); + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); context.compile_to_file(OutputKind::ObjectFile, path); let buffer = ModuleBuffer::new(PathBuf::from(path)); let llmod_id = CString::new(&module.name[..]).unwrap(); @@ -652,6 +653,8 @@ pub unsafe fn optimize_thin_module( Some(thin_buffer) => Arc::clone(&thin_buffer.context), None => { let context = Context::default(); + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); let len = thin_module.shared.thin_buffers.len(); let module = &thin_module.shared.serialized_modules[thin_module.idx - len]; match *module { diff --git a/src/back/write.rs b/src/back/write.rs index 9f4194fefe9..978d88ff4f9 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -67,7 +67,11 @@ pub(crate) unsafe fn codegen( ); context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); - //context.add_command_line_option("-fno-use-linker-plugin"); + // FIXME FIXME FIXME: it seems that uncommenting "ADD_ARG ("-fno-use-linker-plugin")" in libgccjit + // make the test fail (undefined symbol main). + // TODO: Perhaps we're not sending this flag somewhere? + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); // TODO(antoyo): remove since we don't want fat objects when it is for Bitcode only. context.add_command_line_option("-ffat-lto-objects"); context.compile_to_file( @@ -86,7 +90,8 @@ pub(crate) unsafe fn codegen( context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); - //context.add_command_line_option("-fno-use-linker-plugin"); + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); context.add_command_line_option("-ffat-lto-objects"); // TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument). context.compile_to_file( @@ -175,7 +180,8 @@ pub(crate) unsafe fn codegen( context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); //context.add_command_line_option("-ffat-lto-objects"); - //context.add_command_line_option("-fno-use-linker-plugin"); + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); // FIXME FIXME FIXME: // /usr/bin/ld: warning: incremental linking of LTO and non-LTO objects; using -flinker-output=nolto-rel which will bypass whole program optimization @@ -215,6 +221,8 @@ pub(crate) unsafe fn codegen( println!("****************************************************************************************************"); let context = Context::default(); + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); if cgcx.target_arch == "x86" || cgcx.target_arch == "x86_64" { // NOTE: it seems we need to use add_driver_option instead of // add_command_line_option here because we use the LTO frontend via gcc. diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 955f9020235..8957f081d31 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -207,6 +207,8 @@ fn handle_native(name: &str) -> &str { { // Get the native arch. let context = Context::default(); + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); context.get_target_info().arch().unwrap().to_str().unwrap() } #[cfg(not(feature = "master"))] diff --git a/src/lib.rs b/src/lib.rs index 555f164e53f..54bdac8a3c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -195,6 +195,8 @@ impl CodegenBackend for GccCodegenBackend { // Get the second TargetInfo with the correct CPU features by setting the arch. let context = Context::default(); + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); if target_cpu != "generic" { context.add_command_line_option(format!("-march={}", target_cpu)); } @@ -210,6 +212,8 @@ impl CodegenBackend for GccCodegenBackend { let temp_dir = TempDir::new().expect("cannot create temporary directory"); let temp_file = temp_dir.into_path().join("result.asm"); let check_context = Context::default(); + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); check_context.set_print_errors_to_stderr(false); let _int128_ty = check_context.new_c_type(CType::UInt128t); // NOTE: we cannot just call compile() as this would require other files than libgccjit.so. @@ -267,6 +271,8 @@ impl CodegenBackend for GccCodegenBackend { fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { let context = Context::default(); + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" { context.add_command_line_option("-masm=intel"); } @@ -461,6 +467,8 @@ pub fn __rustc_codegen_backend() -> Box { // Check whether the target supports 128-bit integers, and sized floating point types (like // Float16). let context = Context::default(); + context.add_command_line_option("-fno-use-linker-plugin"); + context.add_driver_option("-fno-use-linker-plugin"); Arc::new(Mutex::new(IntoDynSyncSend(context.get_target_info()))) }; #[cfg(not(feature = "master"))] From 2a5f980369980655179e27967f393528d57da590 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 6 May 2025 17:24:17 -0400 Subject: [PATCH 6/7] Trying more stuff --- src/back/lto.rs | 16 ++++++++++++++-- src/back/write.rs | 35 ++++++++++++++++++++++++++++------- src/base.rs | 2 ++ src/lib.rs | 13 +++++++++---- 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index e11b1a99299..ca7952e3f4b 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -272,6 +272,7 @@ fn fat_lto( // We cannot load and merge GCC contexts in memory like cg_llvm is doing. // Instead, we combine the object files into a single object file. for module in in_memory { + println!("Adding -flto for {}", module.name); let path = tmp_path.path().to_path_buf().join(&module.name); let path = path.to_str().expect("path"); let context = &module.module_llvm.context; @@ -280,6 +281,10 @@ fn fat_lto( context.set_optimization_level(to_gcc_opt_level(config.opt_level)); context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); + context.add_driver_option("-flto=auto"); + context.add_driver_option("-flto-partition=one"); + context.add_command_line_option("-fno-fat-lto-objects"); + context.add_driver_option("-fno-fat-lto-objects"); context.add_command_line_option("-fno-use-linker-plugin"); context.add_driver_option("-fno-use-linker-plugin"); context.compile_to_file(OutputKind::ObjectFile, path); @@ -518,8 +523,9 @@ fn thin_lto( });*/ match module { - SerializedModule::Local(_) => { - //let path = module_buffer.0.to_str().expect("path"); + SerializedModule::Local(ref module) => { + let path = module.0.to_str().expect("path"); + println!("??? Should we add -flto for: {:?}", path); //let my_path = PathBuf::from(path); //let exists = my_path.exists(); /*module.module_llvm.should_combine_object_files = true; @@ -653,6 +659,12 @@ pub unsafe fn optimize_thin_module( Some(thin_buffer) => Arc::clone(&thin_buffer.context), None => { let context = Context::default(); + context.add_command_line_option("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + context.add_driver_option("-flto=auto"); + context.add_driver_option("-flto-partition=one"); + context.add_command_line_option("-fno-fat-lto-objects"); + context.add_driver_option("-fno-fat-lto-objects"); context.add_command_line_option("-fno-use-linker-plugin"); context.add_driver_option("-fno-use-linker-plugin"); let len = thin_module.shared.thin_buffers.len(); diff --git a/src/back/write.rs b/src/back/write.rs index 978d88ff4f9..73ae5960960 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -65,13 +65,18 @@ pub(crate) unsafe fn codegen( "GCC_module_codegen_emit_bitcode", &*module.name, ); + println!("Adding -flto for {}", bc_out.to_str().unwrap()); context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); + context.add_driver_option("-flto=auto"); + context.add_driver_option("-flto-partition=one"); + context.add_command_line_option("-fno-fat-lto-objects"); + context.add_driver_option("-fno-fat-lto-objects"); // FIXME FIXME FIXME: it seems that uncommenting "ADD_ARG ("-fno-use-linker-plugin")" in libgccjit // make the test fail (undefined symbol main). // TODO: Perhaps we're not sending this flag somewhere? context.add_command_line_option("-fno-use-linker-plugin"); - context.add_driver_option("-fno-use-linker-plugin"); + //context.add_driver_option("-fno-use-linker-plugin"); // TODO(antoyo): remove since we don't want fat objects when it is for Bitcode only. context.add_command_line_option("-ffat-lto-objects"); context.compile_to_file( @@ -88,10 +93,15 @@ pub(crate) unsafe fn codegen( // TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); + println!("Adding -flto for {}", bc_out.to_str().unwrap()); context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); + context.add_driver_option("-flto=auto"); + context.add_driver_option("-flto-partition=one"); + context.add_command_line_option("-fno-fat-lto-objects"); + context.add_driver_option("-fno-fat-lto-objects"); context.add_command_line_option("-fno-use-linker-plugin"); - context.add_driver_option("-fno-use-linker-plugin"); + //context.add_driver_option("-fno-use-linker-plugin"); context.add_command_line_option("-ffat-lto-objects"); // TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument). context.compile_to_file( @@ -179,15 +189,20 @@ pub(crate) unsafe fn codegen( if fat_lto { context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); + context.add_driver_option("-flto=auto"); + context.add_driver_option("-flto-partition=one"); + context.add_command_line_option("-fno-fat-lto-objects"); + context.add_driver_option("-fno-fat-lto-objects"); //context.add_command_line_option("-ffat-lto-objects"); context.add_command_line_option("-fno-use-linker-plugin"); - context.add_driver_option("-fno-use-linker-plugin"); + //context.add_driver_option("-fno-use-linker-plugin"); - // FIXME FIXME FIXME: + // FIXME: // /usr/bin/ld: warning: incremental linking of LTO and non-LTO objects; using -flinker-output=nolto-rel which will bypass whole program optimization - // ====> So I'm probably missing -flto somewhere. + // => So I'm probably missing -flto somewhere. + // ====> That was caused because I didn't build the sysroot with LTO. - println!("**** Adding -flto to {:?}", obj_out.to_str().expect("path to str")); + println!("Adding -flto to {:?}", obj_out.to_str().expect("path to str")); // FIXME: the problem is probably that the code is only in GIMPLE IR while // we would want to get the optimized asm done from LTO. @@ -221,8 +236,14 @@ pub(crate) unsafe fn codegen( println!("****************************************************************************************************"); let context = Context::default(); + context.add_command_line_option("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + context.add_driver_option("-flto=auto"); + context.add_driver_option("-flto-partition=one"); + context.add_command_line_option("-fno-fat-lto-objects"); + context.add_driver_option("-fno-fat-lto-objects"); context.add_command_line_option("-fno-use-linker-plugin"); - context.add_driver_option("-fno-use-linker-plugin"); + //context.add_driver_option("-fno-use-linker-plugin"); if cgcx.target_arch == "x86" || cgcx.target_arch == "x86_64" { // NOTE: it seems we need to use add_driver_option instead of // add_command_line_option here because we use the LTO frontend via gcc. diff --git a/src/base.rs b/src/base.rs index 9b495174a3f..27ac59aba29 100644 --- a/src/base.rs +++ b/src/base.rs @@ -100,6 +100,8 @@ pub fn compile_codegen_unit( let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... let context = new_context(tcx); + println!("==== Module codegen: {}", cgu_name); + context.add_driver_option("-fno-use-linker-plugin"); if tcx.sess.panic_strategy() == PanicStrategy::Unwind { context.add_command_line_option("-fexceptions"); diff --git a/src/lib.rs b/src/lib.rs index 54bdac8a3c6..90ee238a8a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -196,7 +196,7 @@ impl CodegenBackend for GccCodegenBackend { // Get the second TargetInfo with the correct CPU features by setting the arch. let context = Context::default(); context.add_command_line_option("-fno-use-linker-plugin"); - context.add_driver_option("-fno-use-linker-plugin"); + //context.add_driver_option("-fno-use-linker-plugin"); if target_cpu != "generic" { context.add_command_line_option(format!("-march={}", target_cpu)); } @@ -213,7 +213,7 @@ impl CodegenBackend for GccCodegenBackend { let temp_file = temp_dir.into_path().join("result.asm"); let check_context = Context::default(); context.add_command_line_option("-fno-use-linker-plugin"); - context.add_driver_option("-fno-use-linker-plugin"); + //context.add_driver_option("-fno-use-linker-plugin"); check_context.set_print_errors_to_stderr(false); let _int128_ty = check_context.new_c_type(CType::UInt128t); // NOTE: we cannot just call compile() as this would require other files than libgccjit.so. @@ -271,8 +271,12 @@ impl CodegenBackend for GccCodegenBackend { fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { let context = Context::default(); + context.add_command_line_option("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + context.add_driver_option("-flto=auto"); + context.add_driver_option("-flto-partition=one"); context.add_command_line_option("-fno-use-linker-plugin"); - context.add_driver_option("-fno-use-linker-plugin"); + //context.add_driver_option("-fno-use-linker-plugin"); if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" { context.add_command_line_option("-masm=intel"); } @@ -306,6 +310,7 @@ impl ExtraBackendMethods for GccCodegenBackend { should_combine_object_files: false, temp_dir: None, }; + mods.context.add_driver_option("-fno-use-linker-plugin"); unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); @@ -468,7 +473,7 @@ pub fn __rustc_codegen_backend() -> Box { // Float16). let context = Context::default(); context.add_command_line_option("-fno-use-linker-plugin"); - context.add_driver_option("-fno-use-linker-plugin"); + //context.add_driver_option("-fno-use-linker-plugin"); Arc::new(Mutex::new(IntoDynSyncSend(context.get_target_info()))) }; #[cfg(not(feature = "master"))] From 7b7aa974f6601e3a9acfb4146b1315504e5c8734 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 10 May 2025 11:25:16 -0400 Subject: [PATCH 7/7] Add note --- src/back/lto.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/back/lto.rs b/src/back/lto.rs index ca7952e3f4b..1e22f72523f 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -283,6 +283,9 @@ fn fat_lto( context.add_command_line_option("-flto-partition=one"); context.add_driver_option("-flto=auto"); context.add_driver_option("-flto-partition=one"); + // FIXME: we apparently generate fat objects since we had trouble with a sync: + // https://blog.antoyo.xyz/rustc_codegen_gcc-progress-report-33 + // TODO: Maybe fix this before removing -fuse-linker-plugin. context.add_command_line_option("-fno-fat-lto-objects"); context.add_driver_option("-fno-fat-lto-objects"); context.add_command_line_option("-fno-use-linker-plugin");