Skip to content
Closed
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
8 changes: 3 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -77,14 +77,12 @@ jobs:

- name: Run tests
run: |
# 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: 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
8 changes: 1 addition & 7 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,7 @@ If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y

### 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)
```
To use LTO, you need to set `lto = "fat"` in the `Cargo.toml`.

### Rustc

Expand Down
9 changes: 1 addition & 8 deletions src/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ use rustc_errors::{DiagCtxtHandle, FatalError};
use rustc_middle::bug;
use rustc_middle::dep_graph::WorkProduct;
use rustc_session::config::Lto;
use rustc_target::spec::RelocModel;
use tempfile::{TempDir, tempdir};

use crate::back::write::save_temp_bitcode;
Expand Down Expand Up @@ -566,13 +565,7 @@ pub fn optimize_thin_module(
};
let module = ModuleCodegen::new_regular(
thin_module.name().to_string(),
GccContext {
context,
should_combine_object_files,
// TODO(antoyo): use the correct relocation model here.
relocation_model: RelocModel::Pic,
temp_dir: None,
},
GccContext { context, should_combine_object_files, temp_dir: None },
);
/*{
let target = &*module.module_llvm.tm;
Expand Down
143 changes: 18 additions & 125 deletions src/back/write.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{env, fs};

use gccjit::{Context, OutputKind};
use gccjit::OutputKind;
use rustc_codegen_ssa::back::link::ensure_removed;
use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig};
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
Expand All @@ -9,7 +9,6 @@ use rustc_session::config::OutputType;
use rustc_span::fatal_error::FatalError;
use rustc_target::spec::SplitDebuginfo;

use crate::base::add_pic_option;
use crate::errors::CopyBitcode;
use crate::{GccCodegenBackend, GccContext};

Expand All @@ -27,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,
Expand All @@ -44,80 +38,24 @@ pub(crate) fn codegen(
);

if config.bitcode_needed() {
if fat_lto {
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"),
);
}
.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);
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);

// 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 @@ -167,61 +105,16 @@ pub(crate) fn codegen(
context.dump_to_file(path, true);
}
if should_combine_object_files {
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");
// 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");

let path = obj_out.to_str().expect("path to str");

if fat_lto {
let lto_path = format!("{}.lto", path);
// cSpell:disable
// FIXME(antoyo): The LTO frontend generates the following warning:
// ../build_sysroot/sysroot_src/library/core/src/num/dec2flt/lemire.rs:150:15: warning: type of ‘_ZN4core3num7dec2flt5table17POWER_OF_FIVE_12817ha449a68fb31379e4E’ does not match original declaration [-Wlto-type-mismatch]
// 150 | let (lo5, hi5) = POWER_OF_FIVE_128[index];
// | ^
// lto1: note: ‘_ZN4core3num7dec2flt5table17POWER_OF_FIVE_12817ha449a68fb31379e4E’ was previously declared here
//
// This option is to mute it to make the UI tests pass with LTO enabled.
// cSpell:enable
context.add_driver_option("-Wno-lto-type-mismatch");
// NOTE: this doesn't actually generate an executable. With the above
// flags, it combines the .o files together in another .o.
context.compile_to_file(OutputKind::Executable, &lto_path);

let context = Context::default();
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.
context.add_driver_option("-masm=intel");
}

// NOTE: these two options are needed to invoke LTO to produce an object file.
// We need to initiate a second compilation because the arguments "-x lto"
// needs to be at the very beginning.
context.add_driver_option("-x");
context.add_driver_option("lto");
add_pic_option(&context, module.module_llvm.relocation_model);
context.add_driver_option(lto_path);

context.compile_to_file(OutputKind::ObjectFile, path);
} else {
// NOTE: this doesn't actually generate an executable. With the above
// flags, it combines the .o files together in another .o.
context.compile_to_file(OutputKind::Executable, path);
}
// NOTE: this doesn't actually generate an executable. With the above
// flags, it combines the .o files together in another .o.
context.compile_to_file(OutputKind::Executable, path);
} else {
context.compile_to_file(
OutputKind::ObjectFile,
Expand Down
1 change: 0 additions & 1 deletion src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ pub fn compile_codegen_unit(
cgu_name.to_string(),
GccContext {
context: Arc::new(SyncContext::new(context)),
relocation_model: tcx.sess.relocation_model(),
should_combine_object_files: false,
temp_dir: None,
},
Expand Down
5 changes: 0 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ use rustc_session::Session;
use rustc_session::config::{OptLevel, OutputFilenames};
use rustc_span::Symbol;
use rustc_span::fatal_error::FatalError;
use rustc_target::spec::RelocModel;
use tempfile::TempDir;

use crate::back::lto::ModuleBuffer;
Expand Down Expand Up @@ -287,7 +286,6 @@ impl ExtraBackendMethods for GccCodegenBackend {
) -> Self::Module {
let mut mods = GccContext {
context: Arc::new(SyncContext::new(new_context(tcx))),
relocation_model: tcx.sess.relocation_model(),
should_combine_object_files: false,
temp_dir: None,
};
Expand Down Expand Up @@ -319,9 +317,6 @@ impl ExtraBackendMethods for GccCodegenBackend {

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,
// Temporary directory used by LTO. We keep it here so that it's not removed before linking.
temp_dir: Option<TempDir>,
Expand Down
Loading