Skip to content

Remove EMBED_LTO_BITCODE #678

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,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 --mini-tests
cargo test
./y.sh clean all
Expand All @@ -73,11 +73,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"
Expand Down
10 changes: 0 additions & 10 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
11 changes: 6 additions & 5 deletions src/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,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 {
Expand Down Expand Up @@ -302,7 +302,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
Expand Down Expand Up @@ -610,7 +610,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 => {
Expand All @@ -621,7 +621,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
Expand All @@ -640,7 +640,8 @@ pub fn optimize_thin_module(
thin_module.name().to_string(),
GccContext {
context,
should_combine_object_files,
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,
Expand Down
102 changes: 35 additions & 67 deletions src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<GccCodegenBackend>,
Expand All @@ -24,12 +24,8 @@ pub(crate) fn codegen(
{
let context = &module.module_llvm.context;

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 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,
Expand All @@ -43,80 +39,49 @@ 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,
);
}*/

// 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_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,
);
.generic_activity_with_arg("GCC_module_codegen_emit_bitcode", &*module.name);
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"),
);
}
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,
);
if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
let _timer = cgcx
.prof
.generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name);
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");
// 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);

// 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"),
);
}
// 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"));
}
}

Expand Down Expand Up @@ -165,7 +130,10 @@ pub(crate) fn codegen(
context.set_debug_info(true);
context.dump_to_file(path, true);
}
if should_combine_object_files {
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 {
context.add_command_line_option("-flto=auto");
context.add_command_line_option("-flto-partition=one");
Expand Down
10 changes: 6 additions & 4 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -74,6 +74,7 @@ pub fn compile_codegen_unit(
tcx: TyCtxt<'_>,
cgu_name: Symbol,
target_info: LockedTargetInfo,
lto_supported: bool,
) -> (ModuleCodegen<GccContext>, u64) {
let prof_timer = tcx.prof.generic_activity("codegen_module");
let start_time = Instant::now();
Expand All @@ -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),
);
Expand All @@ -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<GccContext> {
let cgu = tcx.codegen_unit(cgu_name);
// Instantiate monomorphizations without filling out definitions yet...
Expand Down Expand Up @@ -242,7 +243,8 @@ pub fn compile_codegen_unit(
GccContext {
context: Arc::new(SyncContext::new(context)),
relocation_model: tcx.sess.relocation_model(),
should_combine_object_files: false,
lto_supported,
lto_mode: LtoMode::None,
temp_dir: None,
},
)
Expand Down
54 changes: 46 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,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};
Expand Down Expand Up @@ -181,6 +178,7 @@ impl LockedTargetInfo {
#[derive(Clone)]
pub struct GccCodegenBackend {
target_info: LockedTargetInfo,
lto_supported: Arc<AtomicBool>,
}

impl CodegenBackend for GccCodegenBackend {
Expand All @@ -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");

Expand Down Expand Up @@ -297,7 +318,8 @@ 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,
lto_supported: false,
temp_dir: None,
};

Expand All @@ -312,7 +334,12 @@ impl ExtraBackendMethods for GccCodegenBackend {
tcx: TyCtxt<'_>,
cgu_name: Symbol,
) -> (ModuleCodegen<Self::Module>, 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(
Expand All @@ -326,12 +353,20 @@ impl ExtraBackendMethods for GccCodegenBackend {
}
}

#[derive(Clone, Copy, PartialEq)]
pub enum LtoMode {
None,
Thin,
Fat,
}

pub struct GccContext {
context: Arc<SyncContext>,
/// 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,
lto_supported: bool,
// Temporary directory used by LTO. We keep it here so that it's not removed before linking.
temp_dir: Option<TempDir>,
}
Expand Down Expand Up @@ -468,7 +503,10 @@ pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
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<OptLevel>) -> OptimizationLevel {
Expand Down
Loading