From 8f048e9f09241b8a589512869df07a294d18fa25 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 20 May 2025 07:12:55 -0400 Subject: [PATCH 1/8] 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 1d8eaf9a141..3b2425d150b 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 @@ -79,11 +79,11 @@ jobs: run: | # FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros. echo -n 'lto = "fat"' >> build_system/build_sysroot/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: Run y.sh cargo build 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 859bb1568f4..7aeb13a4da8 100644 --- a/Readme.md +++ b/Readme.md @@ -135,16 +135,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 d03d063bdac..1e2a81a2645 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 37bbe263e3a9a799aea2bc8848c1b36e598b79e4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 20 May 2025 09:26:22 -0400 Subject: [PATCH 2/8] 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 10fce860b77..d4f99cfa2f7 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -41,7 +41,7 @@ use tempfile::{TempDir, tempdir}; use crate::back::write::save_temp_bitcode; use crate::errors::{DynamicLinkingWithLTO, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib}; -use crate::{GccCodegenBackend, GccContext, SyncContext, to_gcc_opt_level}; +use crate::{GccCodegenBackend, GccContext, LtoMode, SyncContext, to_gcc_opt_level}; pub fn crate_type_allows_lto(crate_type: CrateType) -> bool { match crate_type { @@ -303,7 +303,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 @@ -611,7 +611,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 => { @@ -622,7 +622,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 @@ -641,7 +641,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 1e2a81a2645..201805eae69 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -12,7 +12,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 a9d7808c833..22c221b1a03 100644 --- a/src/base.rs +++ b/src/base.rs @@ -21,7 +21,7 @@ use rustc_target::spec::{PanicStrategy, RelocModel}; 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 { @@ -242,7 +242,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 746f5abae26..b98ddf9acb6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -299,7 +299,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, }; @@ -328,12 +328,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 466fb8abd70f6b34024fc32d68ba3d7ef0f31db6 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 20 May 2025 21:15:48 -0400 Subject: [PATCH 3/8] 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 d4f99cfa2f7..a7d3f53366b 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -642,6 +642,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 201805eae69..44aa268b243 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 22c221b1a03..fcaf2987e9c 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... @@ -242,6 +243,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 b98ddf9acb6..73a74608133 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,10 +86,7 @@ mod type_of; use std::any::Any; use std::fmt::Debug; use std::ops::Deref; -#[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}; @@ -183,6 +180,7 @@ impl LockedTargetInfo { #[derive(Clone)] pub struct GccCodegenBackend { target_info: LockedTargetInfo, + lto_supported: Arc, } impl CodegenBackend for GccCodegenBackend { @@ -204,6 +202,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"); @@ -300,6 +321,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, }; @@ -314,7 +336,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( @@ -341,6 +368,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, } @@ -478,7 +506,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 3b7ee43ef12ef9a73916c4d7c782ac7a1d8d6b7d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 15 Jun 2025 09:43:44 -0400 Subject: [PATCH 4/8] 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 a7d3f53366b..128db3a0beb 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; @@ -41,7 +42,7 @@ use tempfile::{TempDir, tempdir}; use crate::back::write::save_temp_bitcode; use crate::errors::{DynamicLinkingWithLTO, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib}; -use crate::{GccCodegenBackend, GccContext, LtoMode, SyncContext, to_gcc_opt_level}; +use crate::{GccCodegenBackend, GccContext, LTO_SUPPORTED, LtoMode, SyncContext, to_gcc_opt_level}; pub fn crate_type_allows_lto(crate_type: CrateType) -> bool { match crate_type { @@ -637,12 +638,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 73a74608133..f74021aa63f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -183,6 +183,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 @@ -202,7 +204,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"); @@ -222,6 +224,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); } @@ -317,11 +320,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 5502a85d8494edbb90783d029366195064540131 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 15 Jun 2025 09:56:32 -0400 Subject: [PATCH 5/8] Fix clippy warning --- Cargo.lock | 50 +++++++++++++++++++++++++++++++++++++++++++------- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 967a51a1cc6..b20c181a8cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,6 +81,18 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + [[package]] name = "hermit-abi" version = "0.3.1" @@ -111,9 +123,9 @@ checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "memchr" @@ -137,6 +149,12 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "regex" version = "1.8.4" @@ -166,9 +184,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.42" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ "bitflags", "errno", @@ -188,12 +206,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.14.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if", "fastrand", + "getrandom", "once_cell", "rustix", "windows-sys", @@ -242,6 +260,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "winapi" version = "0.3.9" @@ -345,3 +372,12 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] diff --git a/Cargo.toml b/Cargo.toml index c692a90f0a4..73261903d58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ gccjit = "2.7" [dev-dependencies] boml = "0.3.1" lang_tester = "0.8.0" -tempfile = "3.7.1" +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 f74021aa63f..ebf1d0b0181 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -207,7 +207,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 721003db68f7df8f92b8ebad37fea04b9d87f012 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 15 Jun 2025 13:43:04 -0400 Subject: [PATCH 6/8] 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 ebf1d0b0181..b6a6bdc7601 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -204,8 +204,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 ff4a123f6e5555deca4674ddb6119aae9be2d880 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 15 Jun 2025 13:43:28 -0400 Subject: [PATCH 7/8] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index f62154968d3..5ad2c6ab9b8 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -04ce66d8c918de9273bd7101638ad8724edf5e21 +9244ae6e2e96e7d255c73fbd4a9f345e0cd96f35 From 46fd6df2ccd5b03fb7ab181c78dd4c74eecbc744 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 15 Jun 2025 17:44:59 -0400 Subject: [PATCH 8/8] 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 44aa268b243..78867b59e6b 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