From b70b3041712b9821395d5244900f4a52a70d3020 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 20 May 2025 07:12:55 -0400 Subject: [PATCH 1/9] Remove EMBED_LTO_BITCODE --- .github/workflows/release.yml | 6 +- Readme.md | 10 --- src/back/write.rs | 114 ++++++++++++---------------------- 3 files changed, 41 insertions(+), 89 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 65ceb691906..a577c2eed71 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,7 +62,7 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - EMBED_LTO_BITCODE=1 ./y.sh build --sysroot --release --release-sysroot + ./y.sh build --sysroot --release --release-sysroot ./y.sh test --cargo-tests ./y.sh clean all @@ -80,11 +80,11 @@ jobs: # FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros. # FIXME(antoyo): this should probably not be needed since we embed the LTO bitcode. printf '[profile.release]\nlto = "fat"\n' >> build/build_sysroot/sysroot_src/library/Cargo.toml - EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot --keep-lto-tests ${{ matrix.commands }} + ./y.sh test --release --clean --release-sysroot --build-sysroot --keep-lto-tests ${{ matrix.commands }} - name: LTO test run: | - EMBED_LTO_BITCODE=1 CHANNEL="release" ./y.sh cargo build --release --manifest-path tests/hello-world/Cargo.toml + CHANNEL="release" ./y.sh cargo build --release --manifest-path tests/hello-world/Cargo.toml call_found=$(objdump -dj .text tests/hello-world/target/release/hello_world | grep -c "call .*mylib.*my_func" ) ||: if [ $call_found -gt 0 ]; then echo "ERROR: call my_func found in asm" diff --git a/Readme.md b/Readme.md index 9cdd59f94f8..cd6aeae4b42 100644 --- a/Readme.md +++ b/Readme.md @@ -141,16 +141,6 @@ $ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. -### LTO - -To use LTO, you need to set the variable `EMBED_LTO_BITCODE=1` in addition to setting `lto = "fat"` in the `Cargo.toml`. - -Failing to set `EMBED_LTO_BITCODE` will give you the following error: - -``` -error: failed to copy bitcode to object file: No such file or directory (os error 2) -``` - ### Rustc If you want to run `rustc` directly, you can do so with: diff --git a/src/back/write.rs b/src/back/write.rs index 84bc7016271..02537e89aba 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -26,11 +26,6 @@ pub(crate) fn codegen( let should_combine_object_files = module.module_llvm.should_combine_object_files; - // NOTE: Only generate object files with GIMPLE when this environment variable is set for - // now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit). - // 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, @@ -43,80 +38,44 @@ pub(crate) fn codegen( ); if config.bitcode_needed() { - if fat_lto { + let _timer = cgcx + .prof + .generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name); + + // TODO(antoyo) + /*if let Some(bitcode_filename) = bc_out.file_name() { + cgcx.prof.artifact_size( + "llvm_bitcode", + bitcode_filename.to_string_lossy(), + data.len() as u64, + ); + }*/ + + if config.emit_bc || config.emit_obj == EmitObj::Bitcode { let _timer = cgcx .prof - .generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name); - - // TODO(antoyo) - /*if let Some(bitcode_filename) = bc_out.file_name() { - cgcx.prof.artifact_size( - "llvm_bitcode", - bitcode_filename.to_string_lossy(), - data.len() as u64, - ); - }*/ - - if config.emit_bc || config.emit_obj == EmitObj::Bitcode { - let _timer = cgcx.prof.generic_activity_with_arg( - "GCC_module_codegen_emit_bitcode", - &*module.name, - ); - context.add_command_line_option("-flto=auto"); - context.add_command_line_option("-flto-partition=one"); - // 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( - OutputKind::ObjectFile, - bc_out.to_str().expect("path to str"), - ); - } - - if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) { - let _timer = cgcx.prof.generic_activity_with_arg( - "GCC_module_codegen_embed_bitcode", - &*module.name, - ); - // TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? - //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); - - context.add_command_line_option("-flto=auto"); - context.add_command_line_option("-flto-partition=one"); - 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( - OutputKind::ObjectFile, - bc_out.to_str().expect("path to str"), - ); - } - } else { - if config.emit_bc || config.emit_obj == EmitObj::Bitcode { - let _timer = cgcx.prof.generic_activity_with_arg( - "GCC_module_codegen_emit_bitcode", - &*module.name, - ); - context.compile_to_file( - OutputKind::ObjectFile, - bc_out.to_str().expect("path to str"), - ); - } - - if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) { - // TODO(antoyo): we might want to emit to emit an error here, saying to set the - // environment variable EMBED_LTO_BITCODE. - let _timer = cgcx.prof.generic_activity_with_arg( - "GCC_module_codegen_embed_bitcode", - &*module.name, - ); - // TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? - //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); + .generic_activity_with_arg("GCC_module_codegen_emit_bitcode", &*module.name); + context.add_command_line_option("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + // 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(OutputKind::ObjectFile, bc_out.to_str().expect("path to str")); + } - // 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( - OutputKind::ObjectFile, - bc_out.to_str().expect("path to str"), - ); - } + if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) { + let _timer = cgcx + .prof + .generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name); + // TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? + //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); + + context.add_command_line_option("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + 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(OutputKind::ObjectFile, bc_out.to_str().expect("path to str")); } } @@ -166,6 +125,9 @@ pub(crate) fn codegen( context.dump_to_file(path, true); } if should_combine_object_files { + let fat_lto = config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full); + // We need to check if we're doing LTO since this code is also used for the + // dummy ThinLTO implementation to combine the object files. if fat_lto { context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); From af86f4e351f828a0b475016765996e347ee2e70b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 20 May 2025 09:26:22 -0400 Subject: [PATCH 2/9] Fix to do LTO when requested --- src/back/lto.rs | 10 +++++----- src/back/write.rs | 8 ++++---- src/base.rs | 4 ++-- src/lib.rs | 11 +++++++++-- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index d29bba2570f..fdd4bdb0e39 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -38,7 +38,7 @@ use tempfile::{TempDir, tempdir}; use crate::back::write::save_temp_bitcode; use crate::errors::LtoBitcodeFromRlib; -use crate::{GccCodegenBackend, GccContext, SyncContext, to_gcc_opt_level}; +use crate::{GccCodegenBackend, GccContext, LtoMode, SyncContext, to_gcc_opt_level}; struct LtoData { // TODO(antoyo): use symbols_below_threshold. @@ -228,7 +228,7 @@ fn fat_lto( info!("linking {:?}", name); match bc_decoded { SerializedModule::Local(ref module_buffer) => { - module.module_llvm.should_combine_object_files = true; + module.module_llvm.lto_mode = LtoMode::Fat; module .module_llvm .context @@ -533,7 +533,7 @@ pub fn optimize_thin_module( // that LLVM Context and Module. //let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); //let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &dcx)? as *const _; - let mut should_combine_object_files = false; + let mut lto_mode = LtoMode::None; let context = match thin_module.shared.thin_buffers.get(thin_module.idx) { Some(thin_buffer) => Arc::clone(&thin_buffer.context), None => { @@ -544,7 +544,7 @@ pub fn optimize_thin_module( SerializedModule::Local(ref module_buffer) => { let path = module_buffer.0.to_str().expect("path"); context.add_driver_option(path); - should_combine_object_files = true; + lto_mode = LtoMode::Thin; /*module.module_llvm.should_combine_object_files = true; module .module_llvm @@ -563,7 +563,7 @@ pub fn optimize_thin_module( thin_module.name().to_string(), GccContext { context, - should_combine_object_files, + lto_mode, // TODO(antoyo): use the correct relocation model here. relocation_model: RelocModel::Pic, temp_dir: None, diff --git a/src/back/write.rs b/src/back/write.rs index 02537e89aba..1bc0402298b 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -10,7 +10,7 @@ use rustc_target::spec::SplitDebuginfo; use crate::base::add_pic_option; use crate::errors::CopyBitcode; -use crate::{GccCodegenBackend, GccContext}; +use crate::{GccCodegenBackend, GccContext, LtoMode}; pub(crate) fn codegen( cgcx: &CodegenContext, @@ -24,7 +24,7 @@ pub(crate) fn codegen( { let context = &module.module_llvm.context; - let should_combine_object_files = module.module_llvm.should_combine_object_files; + let lto_mode = module.module_llvm.lto_mode; let bc_out = cgcx.output_filenames.temp_path_for_cgu( OutputType::Bitcode, @@ -124,8 +124,8 @@ pub(crate) fn codegen( context.set_debug_info(true); context.dump_to_file(path, true); } - if should_combine_object_files { - let fat_lto = config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full); + if lto_mode != LtoMode::None { + let fat_lto = lto_mode == LtoMode::Fat; // We need to check if we're doing LTO since this code is also used for the // dummy ThinLTO implementation to combine the object files. if fat_lto { diff --git a/src/base.rs b/src/base.rs index e8672f49580..4616e46b8c9 100644 --- a/src/base.rs +++ b/src/base.rs @@ -21,7 +21,7 @@ use rustc_target::spec::SymbolVisibility; use crate::builder::Builder; use crate::context::CodegenCx; -use crate::{GccContext, LockedTargetInfo, SyncContext, gcc_util, new_context}; +use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext, gcc_util, new_context}; #[cfg(feature = "master")] pub fn visibility_to_gcc(visibility: Visibility) -> gccjit::Visibility { @@ -247,7 +247,7 @@ pub fn compile_codegen_unit( GccContext { context: Arc::new(SyncContext::new(context)), relocation_model: tcx.sess.relocation_model(), - should_combine_object_files: false, + lto_mode: LtoMode::None, temp_dir: None, }, ) diff --git a/src/lib.rs b/src/lib.rs index ec7eab8489a..79f7d21711e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -290,7 +290,7 @@ impl ExtraBackendMethods for GccCodegenBackend { let mut mods = GccContext { context: Arc::new(SyncContext::new(new_context(tcx))), relocation_model: tcx.sess.relocation_model(), - should_combine_object_files: false, + lto_mode: LtoMode::None, temp_dir: None, }; @@ -319,12 +319,19 @@ impl ExtraBackendMethods for GccCodegenBackend { } } +#[derive(Clone, Copy, PartialEq)] +pub enum LtoMode { + None, + Thin, + Fat, +} + pub struct GccContext { context: Arc, /// This field is needed in order to be able to set the flag -fPIC when necessary when doing /// LTO. relocation_model: RelocModel, - should_combine_object_files: bool, + lto_mode: LtoMode, // Temporary directory used by LTO. We keep it here so that it's not removed before linking. temp_dir: Option, } From b0777f2c07364554dce2110d03460c5f190297c3 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 20 May 2025 21:15:48 -0400 Subject: [PATCH 3/9] Fix to not do LTO when LTO is not enabled in gcc --- src/back/lto.rs | 1 + src/back/write.rs | 24 +++++++++++++++--------- src/base.rs | 6 ++++-- src/lib.rs | 43 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index fdd4bdb0e39..e9088a4e6e8 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -564,6 +564,7 @@ pub fn optimize_thin_module( GccContext { context, lto_mode, + lto_supported: false, // TODO(antoyo): check if this is correct to use this value. // TODO(antoyo): use the correct relocation model here. relocation_model: RelocModel::Pic, temp_dir: None, diff --git a/src/back/write.rs b/src/back/write.rs index 1bc0402298b..a5983925119 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -25,6 +25,7 @@ pub(crate) fn codegen( let context = &module.module_llvm.context; let lto_mode = module.module_llvm.lto_mode; + let lto_supported = module.module_llvm.lto_supported; let bc_out = cgcx.output_filenames.temp_path_for_cgu( OutputType::Bitcode, @@ -51,14 +52,17 @@ pub(crate) fn codegen( ); }*/ + // TODO: only emit if libgccjit is compiled with LTO enabled? if config.emit_bc || config.emit_obj == EmitObj::Bitcode { let _timer = cgcx .prof .generic_activity_with_arg("GCC_module_codegen_emit_bitcode", &*module.name); - context.add_command_line_option("-flto=auto"); - context.add_command_line_option("-flto-partition=one"); - // TODO(antoyo): remove since we don't want fat objects when it is for Bitcode only. - context.add_command_line_option("-ffat-lto-objects"); + if lto_supported { + context.add_command_line_option("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + // 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(OutputKind::ObjectFile, bc_out.to_str().expect("path to str")); } @@ -67,12 +71,14 @@ pub(crate) fn codegen( let _timer = cgcx .prof .generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name); - // TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? - //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); + if lto_supported { + // TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? + //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); - 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("-flto=auto"); + context.add_command_line_option("-flto-partition=one"); + 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(OutputKind::ObjectFile, bc_out.to_str().expect("path to str")); diff --git a/src/base.rs b/src/base.rs index 4616e46b8c9..7cf3a237587 100644 --- a/src/base.rs +++ b/src/base.rs @@ -74,6 +74,7 @@ pub fn compile_codegen_unit( tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: LockedTargetInfo, + lto_supported: bool, ) -> (ModuleCodegen, u64) { let prof_timer = tcx.prof.generic_activity("codegen_module"); let start_time = Instant::now(); @@ -82,7 +83,7 @@ pub fn compile_codegen_unit( let (module, _) = tcx.dep_graph.with_task( dep_node, tcx, - (cgu_name, target_info), + (cgu_name, target_info, lto_supported), module_codegen, Some(dep_graph::hash_result), ); @@ -95,7 +96,7 @@ pub fn compile_codegen_unit( fn module_codegen( tcx: TyCtxt<'_>, - (cgu_name, target_info): (Symbol, LockedTargetInfo), + (cgu_name, target_info, lto_supported): (Symbol, LockedTargetInfo, bool), ) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... @@ -247,6 +248,7 @@ pub fn compile_codegen_unit( GccContext { context: Arc::new(SyncContext::new(context)), relocation_model: tcx.sess.relocation_model(), + lto_supported, lto_mode: LtoMode::None, temp_dir: None, }, diff --git a/src/lib.rs b/src/lib.rs index 79f7d21711e..f48d9452662 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,10 +82,7 @@ use std::any::Any; use std::fmt::Debug; use std::ops::Deref; use std::path::PathBuf; -#[cfg(not(feature = "master"))] -use std::sync::atomic::AtomicBool; -#[cfg(not(feature = "master"))] -use std::sync::atomic::Ordering; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use back::lto::{ThinBuffer, ThinData}; @@ -177,6 +174,7 @@ impl LockedTargetInfo { #[derive(Clone)] pub struct GccCodegenBackend { target_info: LockedTargetInfo, + lto_supported: Arc, } impl CodegenBackend for GccCodegenBackend { @@ -202,6 +200,29 @@ impl CodegenBackend for GccCodegenBackend { **self.target_info.info.lock().expect("lock") = context.get_target_info(); } + // TODO: try the LTO frontend and check if it errors out. If so, do not embed the bitcode. + { + let temp_dir = TempDir::new().expect("cannot create temporary directory"); + let temp_file = temp_dir.into_path().join("result.asm"); + let context = Context::default(); + let object_file_path = temp_file.to_str().expect("path to str"); + context.compile_to_file(gccjit::OutputKind::ObjectFile, object_file_path); + + //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(); + check_context.add_driver_option("-x"); + check_context.add_driver_option("lto"); + check_context.add_driver_option(object_file_path); + check_context.set_print_errors_to_stderr(false); + //context.compile_to_file(gccjit::OutputKind::ObjectFile, temp_file.to_str().expect("path to str")); + // FIXME: compile gives the error as expected, but compile_to_file doesn't. + check_context.compile(); + let error = check_context.get_last_error(); + let lto_supported = error == Ok(None); + self.lto_supported.store(lto_supported, Ordering::SeqCst); + } + #[cfg(feature = "master")] gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); @@ -291,6 +312,7 @@ impl ExtraBackendMethods for GccCodegenBackend { context: Arc::new(SyncContext::new(new_context(tcx))), relocation_model: tcx.sess.relocation_model(), lto_mode: LtoMode::None, + lto_supported: false, temp_dir: None, }; @@ -305,7 +327,12 @@ impl ExtraBackendMethods for GccCodegenBackend { tcx: TyCtxt<'_>, cgu_name: Symbol, ) -> (ModuleCodegen, u64) { - base::compile_codegen_unit(tcx, cgu_name, self.target_info.clone()) + base::compile_codegen_unit( + tcx, + cgu_name, + self.target_info.clone(), + self.lto_supported.load(Ordering::SeqCst), + ) } fn target_machine_factory( @@ -332,6 +359,7 @@ pub struct GccContext { /// LTO. relocation_model: RelocModel, lto_mode: LtoMode, + lto_supported: bool, // Temporary directory used by LTO. We keep it here so that it's not removed before linking. temp_dir: Option, } @@ -443,7 +471,10 @@ pub fn __rustc_codegen_backend() -> Box { supports_128bit_integers: AtomicBool::new(false), }))); - Box::new(GccCodegenBackend { target_info: LockedTargetInfo { info } }) + Box::new(GccCodegenBackend { + lto_supported: Arc::new(AtomicBool::new(false)), + target_info: LockedTargetInfo { info }, + }) } fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { From 2f2a83450755d1e8e4ae43ace2e7817549e5cbcf Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 15 Jun 2025 09:43:44 -0400 Subject: [PATCH 4/9] Fix to forward lto_supported and lto_mode where needed --- src/back/lto.rs | 6 ++++-- src/lib.rs | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index e9088a4e6e8..9071c490013 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -21,6 +21,7 @@ use std::ffi::{CStr, CString}; use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::sync::Arc; +use std::sync::atomic::Ordering; use gccjit::{Context, OutputKind}; use object::read::archive::ArchiveFile; @@ -38,7 +39,7 @@ use tempfile::{TempDir, tempdir}; use crate::back::write::save_temp_bitcode; use crate::errors::LtoBitcodeFromRlib; -use crate::{GccCodegenBackend, GccContext, LtoMode, SyncContext, to_gcc_opt_level}; +use crate::{GccCodegenBackend, GccContext, LTO_SUPPORTED, LtoMode, SyncContext, to_gcc_opt_level}; struct LtoData { // TODO(antoyo): use symbols_below_threshold. @@ -559,12 +560,13 @@ pub fn optimize_thin_module( Arc::new(SyncContext::new(context)) } }; + let lto_supported = LTO_SUPPORTED.load(Ordering::SeqCst); let module = ModuleCodegen::new_regular( thin_module.name().to_string(), GccContext { context, lto_mode, - lto_supported: false, // TODO(antoyo): check if this is correct to use this value. + lto_supported, // TODO(antoyo): use the correct relocation model here. relocation_model: RelocModel::Pic, temp_dir: None, diff --git a/src/lib.rs b/src/lib.rs index f48d9452662..ec3f5a919ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -177,6 +177,8 @@ pub struct GccCodegenBackend { lto_supported: Arc, } +static LTO_SUPPORTED: AtomicBool = AtomicBool::new(false); + impl CodegenBackend for GccCodegenBackend { fn locale_resource(&self) -> &'static str { crate::DEFAULT_LOCALE_RESOURCE @@ -200,7 +202,7 @@ impl CodegenBackend for GccCodegenBackend { **self.target_info.info.lock().expect("lock") = context.get_target_info(); } - // TODO: try the LTO frontend and check if it errors out. If so, do not embed the bitcode. + // NOTE: try the LTO frontend and check if it errors out. If so, do not embed the bitcode. { let temp_dir = TempDir::new().expect("cannot create temporary directory"); let temp_file = temp_dir.into_path().join("result.asm"); @@ -220,6 +222,7 @@ impl CodegenBackend for GccCodegenBackend { check_context.compile(); let error = check_context.get_last_error(); let lto_supported = error == Ok(None); + LTO_SUPPORTED.store(lto_supported, Ordering::SeqCst); self.lto_supported.store(lto_supported, Ordering::SeqCst); } @@ -308,11 +311,12 @@ impl ExtraBackendMethods for GccCodegenBackend { kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind, ) -> Self::Module { + let lto_supported = self.lto_supported.load(Ordering::SeqCst); let mut mods = GccContext { context: Arc::new(SyncContext::new(new_context(tcx))), relocation_model: tcx.sess.relocation_model(), lto_mode: LtoMode::None, - lto_supported: false, + lto_supported, temp_dir: None, }; From 0166bfc4fb5af4efb86aee5136263e0a21de47a0 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 1 Jul 2025 09:27:34 -0400 Subject: [PATCH 5/9] Fix clippy warning --- Cargo.toml | 1 + src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6031933bd2d..2afa0c2a166 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ gccjit = "2.8" [dev-dependencies] boml = "0.3.1" lang_tester = "0.8.0" +tempfile = "3.20.0" [profile.dev] # By compiling dependencies with optimizations, performing tests gets much faster. diff --git a/src/lib.rs b/src/lib.rs index ec3f5a919ab..f30f3f1ed15 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -205,7 +205,7 @@ impl CodegenBackend for GccCodegenBackend { // NOTE: try the LTO frontend and check if it errors out. If so, do not embed the bitcode. { let temp_dir = TempDir::new().expect("cannot create temporary directory"); - let temp_file = temp_dir.into_path().join("result.asm"); + let temp_file = temp_dir.keep().join("result.asm"); let context = Context::default(); let object_file_path = temp_file.to_str().expect("path to str"); context.compile_to_file(gccjit::OutputKind::ObjectFile, object_file_path); From 7a5ee0f585c978e4cba8b53736c85820ba0ef816 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 15 Jun 2025 13:43:04 -0400 Subject: [PATCH 6/9] Only check if LTO is enabled when using the master branch of libgccjit --- src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index f30f3f1ed15..1e14d6bd60d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -202,8 +202,15 @@ impl CodegenBackend for GccCodegenBackend { **self.target_info.info.lock().expect("lock") = context.get_target_info(); } - // NOTE: try the LTO frontend and check if it errors out. If so, do not embed the bitcode. + // While not required by the API, we gate this code on the master feature to make sure we + // don't abort the process while checking if LTO is supported. + // The following could will emit a fatal error if LTO is not supported and older versions + // of libgccjit (the ones without this commit: + // https://github.com/rust-lang/gcc/commit/a073b06800f064b3917a6113d4cc2a0c19a10fda) will + // abort on fatal errors. + #[cfg(feature = "master")] { + // NOTE: try the LTO frontend and check if it errors out. If so, do not embed the bitcode. let temp_dir = TempDir::new().expect("cannot create temporary directory"); let temp_file = temp_dir.keep().join("result.asm"); let context = Context::default(); From 81bbe140a5d222ee809b397b5655f74280094e17 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 15 Jun 2025 17:44:59 -0400 Subject: [PATCH 7/9] Remove comment --- src/back/write.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/back/write.rs b/src/back/write.rs index a5983925119..9f3ac6f682e 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -52,7 +52,6 @@ pub(crate) fn codegen( ); }*/ - // TODO: only emit if libgccjit is compiled with LTO enabled? if config.emit_bc || config.emit_obj == EmitObj::Bitcode { let _timer = cgcx .prof From ea362b21f0a31c453394642d38a5f0a6d50cfa7f Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 9 Oct 2025 15:40:06 -0400 Subject: [PATCH 8/9] Fix to remove messages to stderr when LTO is not suppported by using the new API gccjit::is_lto_supported --- Cargo.lock | 8 ++++---- Cargo.toml | 3 +-- src/lib.rs | 31 +++---------------------------- 3 files changed, 8 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a5b972baf98..181d3aa89bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0e310ef75f396cd11b2443b353d55376656ca92c13cba36f92b7aff346ac1a" +checksum = "60362e038e71e4bdc1a5b23fb45e1aba587b5947fe0db58f4871d95608f89eca" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ed7572b30cd32430294dde6fb70822d58e67c6846a548647e8739776a0125b" +checksum = "ddd542c8414e122217551c6af6b7d33acf51a227aee85276f218c087525e01bb" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 2afa0c2a166..d3ff2757857 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = "2.8" +gccjit = "2.10" #gccjit = { git = "https://github.com/rust-lang/gccjit.rs" } # Local copy. @@ -33,7 +33,6 @@ gccjit = "2.8" [dev-dependencies] boml = "0.3.1" lang_tester = "0.8.0" -tempfile = "3.20.0" [profile.dev] # By compiling dependencies with optimizations, performing tests gets much faster. diff --git a/src/lib.rs b/src/lib.rs index 1e14d6bd60d..9854f3843c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -202,39 +202,14 @@ impl CodegenBackend for GccCodegenBackend { **self.target_info.info.lock().expect("lock") = context.get_target_info(); } - // While not required by the API, we gate this code on the master feature to make sure we - // don't abort the process while checking if LTO is supported. - // The following could will emit a fatal error if LTO is not supported and older versions - // of libgccjit (the ones without this commit: - // https://github.com/rust-lang/gcc/commit/a073b06800f064b3917a6113d4cc2a0c19a10fda) will - // abort on fatal errors. #[cfg(feature = "master")] { - // NOTE: try the LTO frontend and check if it errors out. If so, do not embed the bitcode. - let temp_dir = TempDir::new().expect("cannot create temporary directory"); - let temp_file = temp_dir.keep().join("result.asm"); - let context = Context::default(); - let object_file_path = temp_file.to_str().expect("path to str"); - context.compile_to_file(gccjit::OutputKind::ObjectFile, object_file_path); - - //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(); - check_context.add_driver_option("-x"); - check_context.add_driver_option("lto"); - check_context.add_driver_option(object_file_path); - check_context.set_print_errors_to_stderr(false); - //context.compile_to_file(gccjit::OutputKind::ObjectFile, temp_file.to_str().expect("path to str")); - // FIXME: compile gives the error as expected, but compile_to_file doesn't. - check_context.compile(); - let error = check_context.get_last_error(); - let lto_supported = error == Ok(None); + let lto_supported = gccjit::is_lto_supported(); LTO_SUPPORTED.store(lto_supported, Ordering::SeqCst); self.lto_supported.store(lto_supported, Ordering::SeqCst); - } - #[cfg(feature = "master")] - gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); + gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); + } #[cfg(not(feature = "master"))] { From 1e4b27349b8376af1946b6ef2261c88526918d01 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 9 Oct 2025 15:48:29 -0400 Subject: [PATCH 9/9] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index 93cff753b14..b8d4166542b 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -0256a7539a83aa26aade8cca138d9c69634a51b1 +28b84db392ac0a572f1a2a2a1317aa5f2bc742cb