Skip to content

Commit dddd7ab

Browse files
committed
Auto merge of #143161 - GuillaumeGomez:subtree-update_cg_gcc_2025-06-28, r=GuillaumeGomez
GCC backend subtree update cc `@antoyo` r? ghost
2 parents 8141c22 + 3dcbc1e commit dddd7ab

File tree

12 files changed

+150
-117
lines changed

12 files changed

+150
-117
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use std::ffi::OsStr;
2+
use std::path::Path;
3+
4+
use crate::utils::run_command_with_output;
5+
6+
fn show_usage() {
7+
println!(
8+
r#"
9+
`abi-test` command help:
10+
--help : Show this help"#
11+
);
12+
}
13+
14+
pub fn run() -> Result<(), String> {
15+
let mut args = std::env::args().skip(2);
16+
// FractalFir: In the future, I'd like to add some more subcommands / options.
17+
// So, this loop ought to stay for that purpose. It should also stay as a while loop(to parse args)
18+
#[allow(clippy::never_loop, clippy::while_let_on_iterator)]
19+
while let Some(arg) = args.next() {
20+
match arg.as_str() {
21+
"--help" => {
22+
show_usage();
23+
return Ok(());
24+
}
25+
_ => return Err(format!("Unknown option {arg:?}")),
26+
}
27+
}
28+
// Ensure that we have a cloned version of abi-cafe on hand.
29+
crate::utils::git_clone(
30+
"https://github.com/Gankra/abi-cafe.git",
31+
Some("clones/abi-cafe".as_ref()),
32+
true,
33+
)
34+
.map_err(|err| (format!("Git clone failed with message: {err:?}!")))?;
35+
// Configure abi-cafe to use the exact same rustc version we use - this is crucial.
36+
// Otherwise, the concept of ABI compatibility becomes meanignless.
37+
std::fs::copy("rust-toolchain", "clones/abi-cafe/rust-toolchain")
38+
.expect("Could not copy toolchain configs!");
39+
// Get the backend path.
40+
// We will use the *debug* build of the backend - it has more checks enabled.
41+
let backend_path = std::path::absolute("target/debug/librustc_codegen_gcc.so").unwrap();
42+
let backend_arg = format!("--add-rustc-codegen-backend=cg_gcc:{}", backend_path.display());
43+
// Run ABI cafe using cargo.
44+
let cmd: &[&dyn AsRef<OsStr>] = &[
45+
&"cargo",
46+
&"run",
47+
&"--release",
48+
&"--",
49+
&backend_arg,
50+
// Test rust-LLVM to Rust-GCC calls
51+
&"--pairs",
52+
&"rustc_calls_cg_gcc",
53+
&"--pairs",
54+
&"cg_gcc_calls_rustc",
55+
// Test Rust-GCC to C calls
56+
&"--pairs",
57+
&"cg_gcc_calls_c",
58+
&"--pairs",
59+
&"c_calls_cg_gcc",
60+
];
61+
// Run ABI cafe.
62+
run_command_with_output(cmd, Some(Path::new("clones/abi-cafe")))?;
63+
64+
Ok(())
65+
}

compiler/rustc_codegen_gcc/build_system/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::{env, process};
22

3+
mod abi_test;
34
mod build;
45
mod clean;
56
mod clone_gcc;
@@ -12,7 +13,6 @@ mod rust_tools;
1213
mod rustc_info;
1314
mod test;
1415
mod utils;
15-
1616
const BUILD_DIR: &str = "build";
1717

1818
macro_rules! arg_error {
@@ -44,7 +44,8 @@ Commands:
4444
info : Displays information about the build environment and project configuration.
4545
clone-gcc : Clones the GCC compiler from a specified source.
4646
fmt : Runs rustfmt
47-
fuzz : Fuzzes `cg_gcc` using rustlantis"
47+
fuzz : Fuzzes `cg_gcc` using rustlantis
48+
abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM"
4849
);
4950
}
5051

@@ -59,6 +60,7 @@ pub enum Command {
5960
Info,
6061
Fmt,
6162
Fuzz,
63+
AbiTest,
6264
}
6365

6466
fn main() {
@@ -77,6 +79,7 @@ fn main() {
7779
Some("test") => Command::Test,
7880
Some("info") => Command::Info,
7981
Some("clone-gcc") => Command::CloneGcc,
82+
Some("abi-test") => Command::AbiTest,
8083
Some("fmt") => Command::Fmt,
8184
Some("fuzz") => Command::Fuzz,
8285
Some("--help") => {
@@ -102,6 +105,7 @@ fn main() {
102105
Command::CloneGcc => clone_gcc::run(),
103106
Command::Fmt => fmt::run(),
104107
Command::Fuzz => fuzz::run(),
108+
Command::AbiTest => abi_test::run(),
105109
} {
106110
eprintln!("Command failed to run: {e}");
107111
process::exit(1);

compiler/rustc_codegen_gcc/build_system/src/test.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -738,14 +738,7 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> {
738738
let path = get_sysroot_dir().join("sysroot_src/library/coretests");
739739
let _ = remove_dir_all(path.join("target"));
740740
// TODO(antoyo): run in release mode when we fix the failures.
741-
// TODO(antoyo): remove the --skip f16::test_total_cmp when this issue is fixed:
742-
// https://github.com/rust-lang/rust/issues/141503
743-
run_cargo_command(
744-
&[&"test", &"--", &"--skip", &"f16::test_total_cmp"],
745-
Some(&path),
746-
env,
747-
args,
748-
)?;
741+
run_cargo_command(&[&"test"], Some(&path), env, args)?;
749742
Ok(())
750743
}
751744

compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[toolchain]
2-
channel = "nightly-2025-05-21"
2+
channel = "nightly-2025-06-02"
33
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

compiler/rustc_codegen_gcc/src/builder.rs

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
520520
self.block
521521
}
522522

523-
fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> {
524-
let func = cx.rvalue_as_function(func);
523+
fn append_block(_: &'a CodegenCx<'gcc, 'tcx>, func: Function<'gcc>, name: &str) -> Block<'gcc> {
525524
func.new_block(name)
526525
}
527526

@@ -782,6 +781,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
782781
return self.context.new_call(self.location, fmod, &[a, b]);
783782
}
784783
TypeKind::FP128 => {
784+
// TODO(antoyo): use get_simple_function_f128_2args.
785785
let f128_type = self.type_f128();
786786
let fmodf128 = self.context.new_function(
787787
None,
@@ -938,22 +938,36 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
938938
fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
939939
let block = self.llbb();
940940
let function = block.get_function();
941+
// NOTE(FractalFir): In some cases, we *should* skip the call to get_aligned.
942+
// For example, calling `get_aligned` on a i8 is pointless(since it can only be 1 aligned)
943+
// Calling get_aligned on a `u128`/`i128` causes the attribute to become "stacked"
944+
//
945+
// From GCCs perspective:
946+
// __int128_t __attribute__((aligned(16))) __attribute__((aligned(16)))
947+
// and:
948+
// __int128_t __attribute__((aligned(16)))
949+
// are 2 distinct, incompatible types.
950+
//
951+
// So, we skip the call to `get_aligned` in such a case. *Ideally*, we could do this for all the types,
952+
// but the GCC APIs to facilitate this just aren't quite there yet.
953+
954+
// This checks that we only skip `get_aligned` on 128 bit ints if they have the correct alignment.
955+
// Otherwise, this may be an under-aligned load, so we will still call get_aligned.
956+
let mut can_skip_align = (pointee_ty == self.cx.u128_type
957+
|| pointee_ty == self.cx.i128_type)
958+
&& align == self.int128_align;
959+
// We can skip the call to `get_aligned` for byte-sized types with alignment of 1.
960+
can_skip_align = can_skip_align
961+
|| (pointee_ty == self.cx.u8_type || pointee_ty == self.cx.i8_type)
962+
&& align.bytes() == 1;
963+
// Skip the call to `get_aligned` when possible.
964+
let aligned_type =
965+
if can_skip_align { pointee_ty } else { pointee_ty.get_aligned(align.bytes()) };
966+
967+
let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
941968
// NOTE: instead of returning the dereference here, we have to assign it to a variable in
942969
// the current basic block. Otherwise, it could be used in another basic block, causing a
943970
// dereference after a drop, for instance.
944-
// FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
945-
// Ideally, we shouldn't need to do this check.
946-
// FractalFir: the `align == self.int128_align` check ensures we *do* call `get_aligned` if
947-
// the alignment of a `u128`/`i128` is not the one mandated by the ABI. This ensures we handle
948-
// under-aligned loads correctly.
949-
let aligned_type = if (pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type)
950-
&& align == self.int128_align
951-
{
952-
pointee_ty
953-
} else {
954-
pointee_ty.get_aligned(align.bytes())
955-
};
956-
let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
957971
let deref = ptr.dereference(self.location).to_rvalue();
958972
let loaded_value = function.new_local(
959973
self.location,
@@ -1105,7 +1119,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
11051119
// TODO(antoyo)
11061120
}
11071121

1108-
fn store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
1122+
fn store(&mut self, mut val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
1123+
if self.structs_as_pointer.borrow().contains(&val) {
1124+
// NOTE: hack to workaround a limitation of the rustc API: see comment on
1125+
// CodegenCx.structs_as_pointer
1126+
val = val.dereference(self.location).to_rvalue();
1127+
}
1128+
11091129
self.store_with_flags(val, ptr, align, MemFlags::empty())
11101130
}
11111131

@@ -1551,16 +1571,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
15511571
aggregate_value
15521572
}
15531573

1554-
fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
1574+
fn set_personality_fn(&mut self, _personality: Function<'gcc>) {
15551575
#[cfg(feature = "master")]
1556-
{
1557-
let personality = self.rvalue_as_function(_personality);
1558-
self.current_func().set_personality_function(personality);
1559-
}
1576+
self.current_func().set_personality_function(_personality);
15601577
}
15611578

15621579
#[cfg(feature = "master")]
1563-
fn cleanup_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
1580+
fn cleanup_landing_pad(&mut self, pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
15641581
self.set_personality_fn(pers_fn);
15651582

15661583
// NOTE: insert the current block in a variable so that a later call to invoke knows to
@@ -1581,7 +1598,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
15811598
}
15821599

15831600
#[cfg(not(feature = "master"))]
1584-
fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
1601+
fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
15851602
let value1 = self
15861603
.current_func()
15871604
.new_local(self.location, self.u8_type.make_pointer(), "landing_pad0")
@@ -1591,7 +1608,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
15911608
(value1, value2)
15921609
}
15931610

1594-
fn filter_landing_pad(&mut self, pers_fn: RValue<'gcc>) {
1611+
fn filter_landing_pad(&mut self, pers_fn: Function<'gcc>) {
15951612
// TODO(antoyo): generate the correct landing pad
15961613
self.cleanup_landing_pad(pers_fn);
15971614
}

compiler/rustc_codegen_gcc/src/common.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -234,19 +234,6 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
234234
match cv {
235235
Scalar::Int(int) => {
236236
let data = int.to_bits(layout.size(self));
237-
238-
// FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code
239-
// the paths for floating-point values.
240-
// TODO: Remove this code?
241-
/*if ty == self.float_type {
242-
return self
243-
.context
244-
.new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64);
245-
}
246-
if ty == self.double_type {
247-
return self.context.new_rvalue_from_double(ty, f64::from_bits(data as u64));
248-
}*/
249-
250237
let value = self.const_uint_big(self.type_ix(bitsize), data);
251238
let bytesize = layout.size(self).bytes();
252239
if bitsize > 1 && ty.is_integral() && bytesize as u32 == ty.get_size() {

0 commit comments

Comments
 (0)