diff options
Diffstat (limited to 'compiler/rustc_codegen_gcc')
20 files changed, 282 insertions, 285 deletions
diff --git a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml b/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml index 931f6097abc..29a3bcec304 100644 --- a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml +++ b/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml @@ -6,6 +6,7 @@ resolver = "2" [dependencies] core = { path = "./sysroot_src/library/core" } +compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" } alloc = { path = "./sysroot_src/library/alloc" } std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] } test = { path = "./sysroot_src/library/test" } diff --git a/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs b/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs new file mode 100644 index 00000000000..3c1531be27a --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs @@ -0,0 +1,65 @@ +use std::ffi::OsStr; +use std::path::Path; + +use crate::utils::run_command_with_output; + +fn show_usage() { + println!( + r#" +`abi-test` command help: + --help : Show this help"# + ); +} + +pub fn run() -> Result<(), String> { + let mut args = std::env::args().skip(2); + // FractalFir: In the future, I'd like to add some more subcommands / options. + // So, this loop ought to stay for that purpose. It should also stay as a while loop(to parse args) + #[allow(clippy::never_loop, clippy::while_let_on_iterator)] + while let Some(arg) = args.next() { + match arg.as_str() { + "--help" => { + show_usage(); + return Ok(()); + } + _ => return Err(format!("Unknown option {arg:?}")), + } + } + // Ensure that we have a cloned version of abi-cafe on hand. + crate::utils::git_clone( + "https://github.com/Gankra/abi-cafe.git", + Some("clones/abi-cafe".as_ref()), + true, + ) + .map_err(|err| (format!("Git clone failed with message: {err:?}!")))?; + // Configure abi-cafe to use the exact same rustc version we use - this is crucial. + // Otherwise, the concept of ABI compatibility becomes meanignless. + std::fs::copy("rust-toolchain", "clones/abi-cafe/rust-toolchain") + .expect("Could not copy toolchain configs!"); + // Get the backend path. + // We will use the *debug* build of the backend - it has more checks enabled. + let backend_path = std::path::absolute("target/debug/librustc_codegen_gcc.so").unwrap(); + let backend_arg = format!("--add-rustc-codegen-backend=cg_gcc:{}", backend_path.display()); + // Run ABI cafe using cargo. + let cmd: &[&dyn AsRef<OsStr>] = &[ + &"cargo", + &"run", + &"--release", + &"--", + &backend_arg, + // Test rust-LLVM to Rust-GCC calls + &"--pairs", + &"rustc_calls_cg_gcc", + &"--pairs", + &"cg_gcc_calls_rustc", + // Test Rust-GCC to C calls + &"--pairs", + &"cg_gcc_calls_c", + &"--pairs", + &"c_calls_cg_gcc", + ]; + // Run ABI cafe. + run_command_with_output(cmd, Some(Path::new("clones/abi-cafe")))?; + + Ok(()) +} diff --git a/compiler/rustc_codegen_gcc/build_system/src/main.rs b/compiler/rustc_codegen_gcc/build_system/src/main.rs index 078a4726ba8..ae975c94fff 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/main.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/main.rs @@ -1,5 +1,6 @@ use std::{env, process}; +mod abi_test; mod build; mod clean; mod clone_gcc; @@ -12,7 +13,6 @@ mod rust_tools; mod rustc_info; mod test; mod utils; - const BUILD_DIR: &str = "build"; macro_rules! arg_error { @@ -44,7 +44,8 @@ Commands: info : Displays information about the build environment and project configuration. clone-gcc : Clones the GCC compiler from a specified source. fmt : Runs rustfmt - fuzz : Fuzzes `cg_gcc` using rustlantis" + fuzz : Fuzzes `cg_gcc` using rustlantis + abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM" ); } @@ -59,6 +60,7 @@ pub enum Command { Info, Fmt, Fuzz, + AbiTest, } fn main() { @@ -77,6 +79,7 @@ fn main() { Some("test") => Command::Test, Some("info") => Command::Info, Some("clone-gcc") => Command::CloneGcc, + Some("abi-test") => Command::AbiTest, Some("fmt") => Command::Fmt, Some("fuzz") => Command::Fuzz, Some("--help") => { @@ -102,6 +105,7 @@ fn main() { Command::CloneGcc => clone_gcc::run(), Command::Fmt => fmt::run(), Command::Fuzz => fuzz::run(), + Command::AbiTest => abi_test::run(), } { eprintln!("Command failed to run: {e}"); process::exit(1); diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs index bcaab0fb526..cbb0f949383 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/test.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs @@ -9,8 +9,8 @@ use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ create_dir, get_sysroot_dir, get_toolchain, git_clone, git_clone_root_dir, remove_file, - run_command, run_command_with_env, run_command_with_output, run_command_with_output_and_env, - rustc_version_info, split_args, walk_dir, + run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, + split_args, walk_dir, }; type Env = HashMap<String, String>; @@ -485,30 +485,6 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> { run_command_with_output_and_env(&[&"git", &"checkout"], rust_dir, Some(env))?; } - let mut patches = Vec::new(); - walk_dir( - "patches/tests", - &mut |_| Ok(()), - &mut |file_path: &Path| { - patches.push(file_path.to_path_buf()); - Ok(()) - }, - false, - )?; - patches.sort(); - // TODO: remove duplication with prepare.rs by creating a apply_patch function in the utils - // module. - for file_path in patches { - println!("[GIT] apply `{}`", file_path.display()); - let path = Path::new("../..").join(file_path); - run_command_with_output(&[&"git", &"apply", &path], rust_dir)?; - run_command_with_output(&[&"git", &"add", &"-A"], rust_dir)?; - run_command_with_output( - &[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())], - rust_dir, - )?; - } - let cargo = String::from_utf8( run_command_with_env(&[&"rustup", &"which", &"cargo"], rust_dir, Some(env))?.stdout, ) @@ -738,14 +714,7 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { let path = get_sysroot_dir().join("sysroot_src/library/coretests"); let _ = remove_dir_all(path.join("target")); // TODO(antoyo): run in release mode when we fix the failures. - // TODO(antoyo): remove the --skip f16::test_total_cmp when this issue is fixed: - // https://github.com/rust-lang/rust/issues/141503 - run_cargo_command( - &[&"test", &"--", &"--skip", &"f16::test_total_cmp"], - Some(&path), - env, - args, - )?; + run_cargo_command(&[&"test"], Some(&path), env, args)?; Ok(()) } diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index c3bd62e5897..6b6f71edaf8 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -6,6 +6,7 @@ )] #![no_core] #![allow(dead_code, internal_features, non_camel_case_types)] +#![rustfmt::skip] extern crate mini_core; @@ -197,10 +198,10 @@ fn main() { assert_eq!(intrinsics::align_of::<u16>() as u8, 2); assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8); - assert!(!intrinsics::needs_drop::<u8>()); - assert!(!intrinsics::needs_drop::<[u8]>()); - assert!(intrinsics::needs_drop::<NoisyDrop>()); - assert!(intrinsics::needs_drop::<NoisyDropUnsized>()); + assert!(!const { intrinsics::needs_drop::<u8>() }); + assert!(!const { intrinsics::needs_drop::<[u8]>() }); + assert!(const { intrinsics::needs_drop::<NoisyDrop>() }); + assert!(const { intrinsics::needs_drop::<NoisyDropUnsized>() }); Unique { pointer: 0 as *const &str, diff --git a/compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch b/compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch deleted file mode 100644 index 39266e081ed..00000000000 --- a/compiler/rustc_codegen_gcc/patches/0001-Pin-compiler_builtins-to-0.1.160.patch +++ /dev/null @@ -1,39 +0,0 @@ -From cdb3d407740e4f15c3746051f8ba89b8e74e99d3 Mon Sep 17 00:00:00 2001 -From: None <none@example.com> -Date: Fri, 30 May 2025 13:46:22 -0400 -Subject: [PATCH] Pin compiler_builtins to 0.1.160 - ---- - library/alloc/Cargo.toml | 2 +- - library/std/Cargo.toml | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml -index 9d0d957..365c9dc 100644 ---- a/library/alloc/Cargo.toml -+++ b/library/alloc/Cargo.toml -@@ -16,7 +16,7 @@ bench = false - - [dependencies] - core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.159", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.160", features = ['rustc-dep-of-std'] } - - [features] - compiler-builtins-mem = ['compiler_builtins/mem'] -diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml -index 4ff4895..31371f0 100644 ---- a/library/std/Cargo.toml -+++ b/library/std/Cargo.toml -@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } - panic_unwind = { path = "../panic_unwind", optional = true } - panic_abort = { path = "../panic_abort" } - core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.159" } -+compiler_builtins = { version = "=0.1.160" } - unwind = { path = "../unwind" } - hashbrown = { version = "0.15", default-features = false, features = [ - 'rustc-dep-of-std', --- -2.49.0 - diff --git a/compiler/rustc_codegen_gcc/patches/tests/0001-Workaround-to-make-a-run-make-test-pass.patch b/compiler/rustc_codegen_gcc/patches/tests/0001-Workaround-to-make-a-run-make-test-pass.patch deleted file mode 100644 index a329d09a95e..00000000000 --- a/compiler/rustc_codegen_gcc/patches/tests/0001-Workaround-to-make-a-run-make-test-pass.patch +++ /dev/null @@ -1,25 +0,0 @@ -From a131c69e54b5c02fe3b517e8f3ad23d4f784ffc8 Mon Sep 17 00:00:00 2001 -From: Antoni Boucher <bouanto@zoho.com> -Date: Fri, 13 Jun 2025 20:25:33 -0400 -Subject: [PATCH] Workaround to make a run-make test pass - ---- - tests/run-make/linker-warning/rmake.rs | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs -index bc21739fefc..0946a7e2a48 100644 ---- a/tests/run-make/linker-warning/rmake.rs -+++ b/tests/run-make/linker-warning/rmake.rs -@@ -55,7 +55,7 @@ fn main() { - diff() - .expected_file("short-error.txt") - .actual_text("(linker error)", out.stderr()) -- .normalize(r#"/rustc[^/]*/"#, "/rustc/") -+ .normalize(r#"/tmp/rustc[^/]*/"#, "/tmp/rustc/") - .normalize( - regex::escape(run_make_support::build_root().to_str().unwrap()), - "/build-root", --- -2.49.0 - diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain index bafe497a2a2..bccbc6cd2c5 100644 --- a/compiler/rustc_codegen_gcc/rust-toolchain +++ b/compiler/rustc_codegen_gcc/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-05-21" +channel = "nightly-2025-06-28" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs index 08f3d281904..0b359f1c5c8 100644 --- a/compiler/rustc_codegen_gcc/src/abi.rs +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -1,7 +1,9 @@ #[cfg(feature = "master")] use gccjit::FnAttribute; use gccjit::{ToLValue, ToRValue, Type}; -use rustc_abi::{ArmCall, CanonAbi, InterruptKind, Reg, RegKind, X86Call}; +#[cfg(feature = "master")] +use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call}; +use rustc_abi::{Reg, RegKind}; use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeCodegenMethods}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index a2e34d1f8fb..b1785af444a 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -520,8 +520,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.block } - fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> { - let func = cx.rvalue_as_function(func); + fn append_block(_: &'a CodegenCx<'gcc, 'tcx>, func: Function<'gcc>, name: &str) -> Block<'gcc> { func.new_block(name) } @@ -539,11 +538,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn ret(&mut self, mut value: RValue<'gcc>) { - if self.structs_as_pointer.borrow().contains(&value) { - // NOTE: hack to workaround a limitation of the rustc API: see comment on - // CodegenCx.structs_as_pointer - value = value.dereference(self.location).to_rvalue(); - } let expected_return_type = self.current_func().get_return_type(); if !expected_return_type.is_compatible_with(value.get_type()) { // NOTE: due to opaque pointers now being used, we need to cast here. @@ -701,7 +695,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let a = self.gcc_int_cast(a, a_type); let b_type = b.get_type().to_unsigned(self); let b = self.gcc_int_cast(b, b_type); - a / b + self.gcc_udiv(a, b) } fn sdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -713,8 +707,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // FIXME(antoyo): rustc_codegen_ssa::mir::intrinsic uses different types for a and b but they // should be the same. let typ = a.get_type().to_signed(self); - let b = self.context.new_cast(self.location, b, typ); - a / b + let b = self.gcc_int_cast(b, typ); + self.gcc_sdiv(a, b) } fn fdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -782,6 +776,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { return self.context.new_call(self.location, fmod, &[a, b]); } TypeKind::FP128 => { + // TODO(antoyo): use get_simple_function_f128_2args. let f128_type = self.type_f128(); let fmodf128 = self.context.new_function( None, @@ -938,22 +933,36 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> { let block = self.llbb(); let function = block.get_function(); + // NOTE(FractalFir): In some cases, we *should* skip the call to get_aligned. + // For example, calling `get_aligned` on a i8 is pointless(since it can only be 1 aligned) + // Calling get_aligned on a `u128`/`i128` causes the attribute to become "stacked" + // + // From GCCs perspective: + // __int128_t __attribute__((aligned(16))) __attribute__((aligned(16))) + // and: + // __int128_t __attribute__((aligned(16))) + // are 2 distinct, incompatible types. + // + // So, we skip the call to `get_aligned` in such a case. *Ideally*, we could do this for all the types, + // but the GCC APIs to facilitate this just aren't quite there yet. + + // This checks that we only skip `get_aligned` on 128 bit ints if they have the correct alignment. + // Otherwise, this may be an under-aligned load, so we will still call get_aligned. + let mut can_skip_align = (pointee_ty == self.cx.u128_type + || pointee_ty == self.cx.i128_type) + && align == self.int128_align; + // We can skip the call to `get_aligned` for byte-sized types with alignment of 1. + can_skip_align = can_skip_align + || (pointee_ty == self.cx.u8_type || pointee_ty == self.cx.i8_type) + && align.bytes() == 1; + // Skip the call to `get_aligned` when possible. + let aligned_type = + if can_skip_align { pointee_ty } else { pointee_ty.get_aligned(align.bytes()) }; + + let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer()); // NOTE: instead of returning the dereference here, we have to assign it to a variable in // the current basic block. Otherwise, it could be used in another basic block, causing a // dereference after a drop, for instance. - // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type. - // Ideally, we shouldn't need to do this check. - // FractalFir: the `align == self.int128_align` check ensures we *do* call `get_aligned` if - // the alignment of a `u128`/`i128` is not the one mandated by the ABI. This ensures we handle - // under-aligned loads correctly. - let aligned_type = if (pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type) - && align == self.int128_align - { - pointee_ty - } else { - pointee_ty.get_aligned(align.bytes()) - }; - let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer()); let deref = ptr.dereference(self.location).to_rvalue(); let loaded_value = function.new_local( self.location, @@ -1488,16 +1497,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { element.get_address(self.location) } else if value_type.dyncast_vector().is_some() { panic!(); - } else if let Some(pointer_type) = value_type.get_pointee() { - if let Some(struct_type) = pointer_type.is_struct() { - // NOTE: hack to workaround a limitation of the rustc API: see comment on - // CodegenCx.structs_as_pointer - aggregate_value - .dereference_field(self.location, struct_type.get_field(idx as i32)) - .to_rvalue() - } else { - panic!("Unexpected type {:?}", value_type); - } } else if let Some(struct_type) = value_type.is_struct() { aggregate_value .access_field(self.location, struct_type.get_field(idx as i32)) @@ -1517,21 +1516,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { assert_eq!(idx as usize as u64, idx); let value_type = aggregate_value.get_type(); + let new_val = self.current_func().new_local(None, value_type, "aggregate_value"); + self.block.add_assignment(None, new_val, aggregate_value); + let lvalue = if value_type.dyncast_array().is_some() { let index = self .context .new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); - self.context.new_array_access(self.location, aggregate_value, index) + self.context.new_array_access(self.location, new_val, index) } else if value_type.dyncast_vector().is_some() { panic!(); - } else if let Some(pointer_type) = value_type.get_pointee() { - if let Some(struct_type) = pointer_type.is_struct() { - // NOTE: hack to workaround a limitation of the rustc API: see comment on - // CodegenCx.structs_as_pointer - aggregate_value.dereference_field(self.location, struct_type.get_field(idx as i32)) - } else { - panic!("Unexpected type {:?}", value_type); - } + } else if let Some(struct_type) = value_type.is_struct() { + new_val.access_field(None, struct_type.get_field(idx as i32)) } else { panic!("Unexpected type {:?}", value_type); }; @@ -1548,19 +1544,16 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.llbb().add_assignment(self.location, lvalue, value); - aggregate_value + new_val.to_rvalue() } - fn set_personality_fn(&mut self, _personality: RValue<'gcc>) { + fn set_personality_fn(&mut self, _personality: Function<'gcc>) { #[cfg(feature = "master")] - { - let personality = self.rvalue_as_function(_personality); - self.current_func().set_personality_function(personality); - } + self.current_func().set_personality_function(_personality); } #[cfg(feature = "master")] - fn cleanup_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { + fn cleanup_landing_pad(&mut self, pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { self.set_personality_fn(pers_fn); // NOTE: insert the current block in a variable so that a later call to invoke knows to @@ -1581,7 +1574,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } #[cfg(not(feature = "master"))] - fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { + fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { let value1 = self .current_func() .new_local(self.location, self.u8_type.make_pointer(), "landing_pad0") @@ -1591,9 +1584,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { (value1, value2) } - fn filter_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { + fn filter_landing_pad(&mut self, pers_fn: Function<'gcc>) { // TODO(antoyo): generate the correct landing pad - self.cleanup_landing_pad(pers_fn) + self.cleanup_landing_pad(pers_fn); } #[cfg(feature = "master")] diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 58ff2f1f8f0..dd582834fac 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -117,15 +117,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> { let local = self.current_func.borrow().expect("func").new_local(None, typ, "undefined"); - if typ.is_struct().is_some() { - // NOTE: hack to workaround a limitation of the rustc API: see comment on - // CodegenCx.structs_as_pointer - let pointer = local.get_address(None); - self.structs_as_pointer.borrow_mut().insert(pointer); - pointer - } else { - local.to_rvalue() - } + local.to_rvalue() } fn const_poison(&self, typ: Type<'gcc>) -> RValue<'gcc> { @@ -234,19 +226,6 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { match cv { Scalar::Int(int) => { let data = int.to_bits(layout.size(self)); - - // FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code - // the paths for floating-point values. - // TODO: Remove this code? - /*if ty == self.float_type { - return self - .context - .new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64); - } - if ty == self.double_type { - return self.context.new_rvalue_from_double(ty, f64::from_bits(data as u64)); - }*/ - let value = self.const_uint_big(self.type_ix(bitsize), data); let bytesize = layout.size(self).bytes(); if bitsize > 1 && ty.is_integral() && bytesize as u32 == ty.get_size() { @@ -261,7 +240,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { } } Scalar::Ptr(ptr, _size) => { - let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative + let (prov, offset) = ptr.prov_and_relative_offset(); let alloc_id = prov.alloc_id(); let base_addr = match self.tcx.global_alloc(alloc_id) { GlobalAlloc::Memory(alloc) => { diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index ff141ad365b..665cf22ddba 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -118,19 +118,12 @@ pub struct CodegenCx<'gcc, 'tcx> { /// A counter that is used for generating local symbol names local_gen_sym_counter: Cell<usize>, - eh_personality: Cell<Option<RValue<'gcc>>>, + eh_personality: Cell<Option<Function<'gcc>>>, #[cfg(feature = "master")] pub rust_try_fn: Cell<Option<(Type<'gcc>, Function<'gcc>)>>, pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>, - /// NOTE: a hack is used because the rustc API is not suitable to libgccjit and as such, - /// `const_undef()` returns struct as pointer so that they can later be assigned a value. - /// As such, this set remembers which of these pointers were returned by this function so that - /// they can be dereferenced later. - /// FIXME(antoyo): fix the rustc API to avoid having this hack. - pub structs_as_pointer: RefCell<FxHashSet<RValue<'gcc>>>, - #[cfg(feature = "master")] pub cleanup_blocks: RefCell<FxHashSet<Block<'gcc>>>, /// The alignment of a u128/i128 type. @@ -155,6 +148,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type)) .unwrap(); let align = layout.align.abi.bytes(); + // For types with size 1, the alignment can be 1 and only 1 + // So, we can skip the call to ``get_aligned`. + // In the future, we can add a GCC API to query the type align, + // and call `get_aligned` if and only if that differs from Rust's expectations. + if layout.size.bytes() == 1 { + return context.new_c_type(ctype); + } #[cfg(feature = "master")] { context.new_c_type(ctype).get_aligned(align) @@ -296,7 +296,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { #[cfg(feature = "master")] rust_try_fn: Cell::new(None), pointee_infos: Default::default(), - structs_as_pointer: Default::default(), #[cfg(feature = "master")] cleanup_blocks: Default::default(), }; @@ -373,8 +372,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> { type Value = RValue<'gcc>; type Metadata = RValue<'gcc>; - // TODO(antoyo): change to Function<'gcc>. - type Function = RValue<'gcc>; + type Function = Function<'gcc>; type BasicBlock = Block<'gcc>; type Type = Type<'gcc>; @@ -392,11 +390,10 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { &self.vtables } - fn get_fn(&self, instance: Instance<'tcx>) -> RValue<'gcc> { + fn get_fn(&self, instance: Instance<'tcx>) -> Function<'gcc> { let func = get_fn(self, instance); *self.current_func.borrow_mut() = Some(func); - // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API. - unsafe { std::mem::transmute(func) } + func } fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> { @@ -420,7 +417,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { ptr } - fn eh_personality(&self) -> RValue<'gcc> { + fn eh_personality(&self) -> Function<'gcc> { // The exception handling personality function. // // If our compilation unit has the `eh_personality` lang item somewhere @@ -458,9 +455,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let symbol_name = tcx.symbol_name(instance).name; let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(FunctionType::Extern); - let func = self.declare_fn(symbol_name, fn_abi); - let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; - func + self.declare_fn(symbol_name, fn_abi) } _ => { let name = if wants_msvc_seh(self.sess()) { @@ -468,8 +463,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } else { "rust_eh_personality" }; - let func = self.declare_func(name, self.type_i32(), &[], true); - unsafe { std::mem::transmute::<Function<'gcc>, RValue<'gcc>>(func) } + self.declare_func(name, self.type_i32(), &[], true) } }; // TODO(antoyo): apply target cpu attributes. @@ -481,11 +475,11 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { self.tcx.sess } - fn set_frame_pointer_type(&self, _llfn: RValue<'gcc>) { + fn set_frame_pointer_type(&self, _llfn: Function<'gcc>) { // TODO(antoyo) } - fn apply_target_cpu_attr(&self, _llfn: RValue<'gcc>) { + fn apply_target_cpu_attr(&self, _llfn: Function<'gcc>) { // TODO(antoyo) } diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index 3a265fbc64f..4c8585192a1 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -1,7 +1,7 @@ use std::ops::Range; use std::sync::Arc; -use gccjit::{Location, RValue}; +use gccjit::{Function, Location, RValue}; use rustc_abi::Size; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; @@ -221,7 +221,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { &self, instance: Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - llfn: RValue<'gcc>, + llfn: Function<'gcc>, mir: &mir::Body<'tcx>, ) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>> { if self.sess().opts.debuginfo == DebugInfo::None { @@ -272,7 +272,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { &self, _instance: Instance<'tcx>, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - _maybe_definition_llfn: Option<RValue<'gcc>>, + _maybe_definition_llfn: Option<Function<'gcc>>, ) -> Self::DIScope { // TODO(antoyo): implement. } diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs index bed82073e2c..691fd8729e3 100644 --- a/compiler/rustc_codegen_gcc/src/declare.rs +++ b/compiler/rustc_codegen_gcc/src/declare.rs @@ -94,7 +94,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { _fn_type: Type<'gcc>, #[cfg(feature = "master")] callconv: Option<FnAttribute<'gcc>>, #[cfg(not(feature = "master"))] callconv: Option<()>, - ) -> RValue<'gcc> { + ) -> Function<'gcc> { // TODO(antoyo): use the fn_type parameter. let const_string = self.context.new_type::<u8>().make_pointer().make_pointer(); let return_type = self.type_i32(); @@ -111,8 +111,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { // NOTE: it is needed to set the current_func here as well, because get_fn() is not called // for the main function. *self.current_func.borrow_mut() = Some(func); - // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API. - unsafe { std::mem::transmute(func) } + func } pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs index f0352c5e6e5..915ed875e32 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs @@ -1,9 +1,9 @@ // File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py` // DO NOT EDIT IT! /// Translate a given LLVM intrinsic name to an equivalent GCC one. -fn map_arch_intrinsic(name: &str) -> &str { - let Some(name) = name.strip_prefix("llvm.") else { - unimplemented!("***** unsupported LLVM intrinsic {}", name) +fn map_arch_intrinsic(full_name: &str) -> &'static str { + let Some(name) = full_name.strip_prefix("llvm.") else { + unimplemented!("***** unsupported LLVM intrinsic {}", full_name) }; let Some((arch, name)) = name.split_once('.') else { unimplemented!("***** unsupported LLVM intrinsic {}", name) @@ -11,7 +11,7 @@ fn map_arch_intrinsic(name: &str) -> &str { match arch { "AMDGPU" => { #[allow(non_snake_case)] - fn AMDGPU(name: &str) -> &str { + fn AMDGPU(name: &str, full_name: &str) -> &'static str { match name { // AMDGPU "div.fixup.f32" => "__builtin_amdgpu_div_fixup", @@ -42,14 +42,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "trig.preop.f64" => "__builtin_amdgpu_trig_preop", "trig.preop.v2f64" => "__builtin_amdgpu_trig_preop", "trig.preop.v4f32" => "__builtin_amdgpu_trig_preop", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - AMDGPU(name) + AMDGPU(name, full_name) } "aarch64" => { #[allow(non_snake_case)] - fn aarch64(name: &str) -> &str { + fn aarch64(name: &str, full_name: &str) -> &'static str { match name { // aarch64 "chkfeat" => "__builtin_arm_chkfeat", @@ -75,14 +75,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "tcommit" => "__builtin_arm_tcommit", "tstart" => "__builtin_arm_tstart", "ttest" => "__builtin_arm_ttest", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - aarch64(name) + aarch64(name, full_name) } "amdgcn" => { #[allow(non_snake_case)] - fn amdgcn(name: &str) -> &str { + fn amdgcn(name: &str, full_name: &str) -> &'static str { match name { // amdgcn "alignbyte" => "__builtin_amdgcn_alignbyte", @@ -99,6 +99,8 @@ fn map_arch_intrinsic(name: &str) -> &str { "cvt.f32.fp8" => "__builtin_amdgcn_cvt_f32_fp8", "cvt.off.f32.i4" => "__builtin_amdgcn_cvt_off_f32_i4", "cvt.pk.bf8.f32" => "__builtin_amdgcn_cvt_pk_bf8_f32", + "cvt.pk.f16.bf8" => "__builtin_amdgcn_cvt_pk_f16_bf8", + "cvt.pk.f16.fp8" => "__builtin_amdgcn_cvt_pk_f16_fp8", "cvt.pk.f32.bf8" => "__builtin_amdgcn_cvt_pk_f32_bf8", "cvt.pk.f32.fp8" => "__builtin_amdgcn_cvt_pk_f32_fp8", "cvt.pk.fp8.f32" => "__builtin_amdgcn_cvt_pk_fp8_f32", @@ -292,6 +294,7 @@ fn map_arch_intrinsic(name: &str) -> &str { "s.sendmsg" => "__builtin_amdgcn_s_sendmsg", "s.sendmsghalt" => "__builtin_amdgcn_s_sendmsghalt", "s.setprio" => "__builtin_amdgcn_s_setprio", + "s.setprio.inc.wg" => "__builtin_amdgcn_s_setprio_inc_wg", "s.setreg" => "__builtin_amdgcn_s_setreg", "s.sleep" => "__builtin_amdgcn_s_sleep", "s.sleep.var" => "__builtin_amdgcn_s_sleep_var", @@ -356,14 +359,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "workitem.id.x" => "__builtin_amdgcn_workitem_id_x", "workitem.id.y" => "__builtin_amdgcn_workitem_id_y", "workitem.id.z" => "__builtin_amdgcn_workitem_id_z", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - amdgcn(name) + amdgcn(name, full_name) } "arm" => { #[allow(non_snake_case)] - fn arm(name: &str) -> &str { + fn arm(name: &str, full_name: &str) -> &'static str { match name { // arm "cdp" => "__builtin_arm_cdp", @@ -465,14 +468,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "usub8" => "__builtin_arm_usub8", "uxtab16" => "__builtin_arm_uxtab16", "uxtb16" => "__builtin_arm_uxtb16", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - arm(name) + arm(name, full_name) } "bpf" => { #[allow(non_snake_case)] - fn bpf(name: &str) -> &str { + fn bpf(name: &str, full_name: &str) -> &'static str { match name { // bpf "btf.type.id" => "__builtin_bpf_btf_type_id", @@ -487,25 +490,25 @@ fn map_arch_intrinsic(name: &str) -> &str { "preserve.field.info" => "__builtin_bpf_preserve_field_info", "preserve.type.info" => "__builtin_bpf_preserve_type_info", "pseudo" => "__builtin_bpf_pseudo", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - bpf(name) + bpf(name, full_name) } "cuda" => { #[allow(non_snake_case)] - fn cuda(name: &str) -> &str { + fn cuda(name: &str, full_name: &str) -> &'static str { match name { // cuda "syncthreads" => "__syncthreads", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - cuda(name) + cuda(name, full_name) } "hexagon" => { #[allow(non_snake_case)] - fn hexagon(name: &str) -> &str { + fn hexagon(name: &str, full_name: &str) -> &'static str { match name { // hexagon "A2.abs" => "__builtin_HEXAGON_A2_abs", @@ -2479,14 +2482,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "prefetch" => "__builtin_HEXAGON_prefetch", "vmemcpy" => "__builtin_hexagon_vmemcpy", "vmemset" => "__builtin_hexagon_vmemset", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - hexagon(name) + hexagon(name, full_name) } "loongarch" => { #[allow(non_snake_case)] - fn loongarch(name: &str) -> &str { + fn loongarch(name: &str, full_name: &str) -> &'static str { match name { // loongarch "asrtgt.d" => "__builtin_loongarch_asrtgt_d", @@ -3988,14 +3991,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "movfcsr2gr" => "__builtin_loongarch_movfcsr2gr", "movgr2fcsr" => "__builtin_loongarch_movgr2fcsr", "syscall" => "__builtin_loongarch_syscall", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - loongarch(name) + loongarch(name, full_name) } "mips" => { #[allow(non_snake_case)] - fn mips(name: &str) -> &str { + fn mips(name: &str, full_name: &str) -> &'static str { match name { // mips "absq.s.ph" => "__builtin_mips_absq_s_ph", @@ -4669,14 +4672,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "wrdsp" => "__builtin_mips_wrdsp", "xor.v" => "__builtin_msa_xor_v", "xori.b" => "__builtin_msa_xori_b", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - mips(name) + mips(name, full_name) } "nvvm" => { #[allow(non_snake_case)] - fn nvvm(name: &str) -> &str { + fn nvvm(name: &str, full_name: &str) -> &'static str { match name { // nvvm "abs.i" => "__nvvm_abs_i", @@ -5024,6 +5027,7 @@ fn map_arch_intrinsic(name: &str) -> &str { "nanosleep" => "__nvvm_nanosleep", "neg.bf16" => "__nvvm_neg_bf16", "neg.bf16x2" => "__nvvm_neg_bf16x2", + "pm.event.mask" => "__nvvm_pm_event_mask", "popc.i" => "__nvvm_popc_i", "popc.ll" => "__nvvm_popc_ll", "prmt" => "__nvvm_prmt", @@ -5448,14 +5452,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "vote.ballot.sync" => "__nvvm_vote_ballot_sync", "vote.uni" => "__nvvm_vote_uni", "vote.uni.sync" => "__nvvm_vote_uni_sync", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - nvvm(name) + nvvm(name, full_name) } "ppc" => { #[allow(non_snake_case)] - fn ppc(name: &str) -> &str { + fn ppc(name: &str, full_name: &str) -> &'static str { match name { // ppc "addex" => "__builtin_ppc_addex", @@ -5842,7 +5846,10 @@ fn map_arch_intrinsic(name: &str) -> &str { "mulhdu" => "__builtin_ppc_mulhdu", "mulhw" => "__builtin_ppc_mulhw", "mulhwu" => "__builtin_ppc_mulhwu", + "national2packed" => "__builtin_ppc_national2packed", "pack.longdouble" => "__builtin_pack_longdouble", + "packed2national" => "__builtin_ppc_packed2national", + "packed2zoned" => "__builtin_ppc_packed2zoned", "pdepd" => "__builtin_pdepd", "pextd" => "__builtin_pextd", "qpx.qvfabs" => "__builtin_qpx_qvfabs", @@ -6035,14 +6042,15 @@ fn map_arch_intrinsic(name: &str) -> &str { "vsx.xxinsertw" => "__builtin_vsx_xxinsertw", "vsx.xxleqv" => "__builtin_vsx_xxleqv", "vsx.xxpermx" => "__builtin_vsx_xxpermx", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + "zoned2packed" => "__builtin_ppc_zoned2packed", + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - ppc(name) + ppc(name, full_name) } "ptx" => { #[allow(non_snake_case)] - fn ptx(name: &str) -> &str { + fn ptx(name: &str, full_name: &str) -> &'static str { match name { // ptx "bar.sync" => "__builtin_ptx_bar_sync", @@ -6063,14 +6071,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "read.pm3" => "__builtin_ptx_read_pm3", "read.smid" => "__builtin_ptx_read_smid", "read.warpid" => "__builtin_ptx_read_warpid", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - ptx(name) + ptx(name, full_name) } "r600" => { #[allow(non_snake_case)] - fn r600(name: &str) -> &str { + fn r600(name: &str, full_name: &str) -> &'static str { match name { // r600 "group.barrier" => "__builtin_r600_group_barrier", @@ -6088,14 +6096,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "read.tidig.x" => "__builtin_r600_read_tidig_x", "read.tidig.y" => "__builtin_r600_read_tidig_y", "read.tidig.z" => "__builtin_r600_read_tidig_z", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - r600(name) + r600(name, full_name) } "riscv" => { #[allow(non_snake_case)] - fn riscv(name: &str) -> &str { + fn riscv(name: &str, full_name: &str) -> &'static str { match name { // riscv "aes32dsi" => "__builtin_riscv_aes32dsi", @@ -6119,14 +6127,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "sha512sum0r" => "__builtin_riscv_sha512sum0r", "sha512sum1" => "__builtin_riscv_sha512sum1", "sha512sum1r" => "__builtin_riscv_sha512sum1r", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - riscv(name) + riscv(name, full_name) } "s390" => { #[allow(non_snake_case)] - fn s390(name: &str) -> &str { + fn s390(name: &str, full_name: &str) -> &'static str { match name { // s390 "bdepg" => "__builtin_s390_bdepg", @@ -6313,14 +6321,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "vupllf" => "__builtin_s390_vupllf", "vupllg" => "__builtin_s390_vupllg", "vupllh" => "__builtin_s390_vupllh", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - s390(name) + s390(name, full_name) } "ve" => { #[allow(non_snake_case)] - fn ve(name: &str) -> &str { + fn ve(name: &str, full_name: &str) -> &'static str { match name { // ve "vl.andm.MMM" => "__builtin_ve_vl_andm_MMM", @@ -7586,14 +7594,14 @@ fn map_arch_intrinsic(name: &str) -> &str { "vl.vxor.vvvvl" => "__builtin_ve_vl_vxor_vvvvl", "vl.xorm.MMM" => "__builtin_ve_vl_xorm_MMM", "vl.xorm.mmm" => "__builtin_ve_vl_xorm_mmm", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - ve(name) + ve(name, full_name) } "x86" => { #[allow(non_snake_case)] - fn x86(name: &str) -> &str { + fn x86(name: &str, full_name: &str) -> &'static str { match name { // x86 "aadd32" => "__builtin_ia32_aadd32", @@ -10154,25 +10162,25 @@ fn map_arch_intrinsic(name: &str) -> &str { "xresldtrk" => "__builtin_ia32_xresldtrk", "xsusldtrk" => "__builtin_ia32_xsusldtrk", "xtest" => "__builtin_ia32_xtest", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - x86(name) + x86(name, full_name) } "xcore" => { #[allow(non_snake_case)] - fn xcore(name: &str) -> &str { + fn xcore(name: &str, full_name: &str) -> &'static str { match name { // xcore "bitrev" => "__builtin_bitrev", "getid" => "__builtin_getid", "getps" => "__builtin_getps", "setps" => "__builtin_setps", - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } - xcore(name) + xcore(name, full_name) } - _ => unimplemented!("***** unsupported LLVM intrinsic {}", name), + _ => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic:{full_name}"), } } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs index 0b77694f115..39dba28b24c 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs @@ -648,6 +648,11 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( new_args.push(handle); args = new_args.into(); } + "__builtin_ia32_rdtscp" => { + let result = builder.current_func().new_local(None, builder.u32_type, "result"); + let new_args = vec![result.get_address(None).to_rvalue()]; + args = new_args.into(); + } _ => (), } } else { @@ -764,6 +769,14 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( new_args.swap(0, 1); args = new_args.into(); } + "__builtin_ia32_dpps256" => { + let mut new_args = args.to_vec(); + // NOTE: without this cast to u8 (and it needs to be a u8 to fix the issue), we + // would get the following error: + // the last argument must be an 8-bit immediate + new_args[2] = builder.context.new_cast(None, new_args[2], builder.cx.type_u8()); + args = new_args.into(); + } _ => (), } } @@ -935,6 +948,19 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( ); return_value = result.to_rvalue(); } + "__builtin_ia32_rdtscp" => { + let field1 = builder.context.new_field(None, return_value.get_type(), "rdtscpField1"); + let return2 = args[0].dereference(None).to_rvalue(); + let field2 = builder.context.new_field(None, return2.get_type(), "rdtscpField2"); + let struct_type = + builder.context.new_struct_type(None, "rdtscpResult", &[field1, field2]); + return_value = builder.context.new_struct_constructor( + None, + struct_type.as_type(), + None, + &[return_value, return2], + ); + } _ => (), } @@ -1529,6 +1555,17 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.aesdecwide128kl" => "__builtin_ia32_aesdecwide128kl_u8", "llvm.x86.aesencwide256kl" => "__builtin_ia32_aesencwide256kl_u8", "llvm.x86.aesdecwide256kl" => "__builtin_ia32_aesdecwide256kl_u8", + "llvm.x86.avx512.uitofp.round.v8f16.v8i16" => "__builtin_ia32_vcvtuw2ph128_mask", + "llvm.x86.avx512.uitofp.round.v16f16.v16i16" => "__builtin_ia32_vcvtuw2ph256_mask", + "llvm.x86.avx512.uitofp.round.v32f16.v32i16" => "__builtin_ia32_vcvtuw2ph512_mask_round", + "llvm.x86.avx512.uitofp.round.v8f16.v8i32" => "__builtin_ia32_vcvtudq2ph256_mask", + "llvm.x86.avx512.uitofp.round.v16f16.v16i32" => "__builtin_ia32_vcvtudq2ph512_mask_round", + "llvm.x86.avx512.uitofp.round.v8f16.v8i64" => "__builtin_ia32_vcvtuqq2ph512_mask_round", + "llvm.x86.avx512.uitofp.round.v8f64.v8i64" => "__builtin_ia32_cvtuqq2pd512_mask", + "llvm.x86.avx512.uitofp.round.v2f64.v2i64" => "__builtin_ia32_cvtuqq2pd128_mask", + "llvm.x86.avx512.uitofp.round.v4f64.v4i64" => "__builtin_ia32_cvtuqq2pd256_mask", + "llvm.x86.avx512.uitofp.round.v8f32.v8i64" => "__builtin_ia32_cvtuqq2ps512_mask", + "llvm.x86.avx512.uitofp.round.v4f32.v4i64" => "__builtin_ia32_cvtuqq2ps256_mask", // TODO: support the tile builtins: "llvm.x86.ldtilecfg" => "__builtin_trap", diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 09132c34aae..497605978fe 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -4,7 +4,9 @@ mod simd; #[cfg(feature = "master")] use std::iter; -use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; +#[cfg(feature = "master")] +use gccjit::Type; +use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] use rustc_abi::ExternAbi; use rustc_abi::{BackendRepr, HasDataLayout}; @@ -112,7 +114,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>( } sym::copysignf32 => "copysignf", sym::copysignf64 => "copysign", - sym::copysignf128 => "copysignl", sym::floorf32 => "floorf", sym::floorf64 => "floor", sym::ceilf32 => "ceilf", @@ -236,6 +237,7 @@ fn get_simple_function_f128_2args<'gcc, 'tcx>( let func_name = match name { sym::maxnumf128 => "fmaxf128", sym::minnumf128 => "fminf128", + sym::copysignf128 => "copysignf128", _ => return None, }; Some(cx.context.new_function( @@ -259,6 +261,7 @@ fn f16_builtin<'gcc, 'tcx>( let f32_type = cx.type_f32(); let builtin_name = match name { sym::ceilf16 => "__builtin_ceilf", + sym::copysignf16 => "__builtin_copysignf", sym::floorf16 => "__builtin_floorf", sym::fmaf16 => "fmaf", sym::maxnumf16 => "__builtin_fmaxf", @@ -300,6 +303,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let fn_args = instance.args; let simple = get_simple_intrinsic(self, name); + // TODO(antoyo): Only call get_simple_function_f128 and get_simple_function_f128_2args when + // it is the symbols for the supported f128 builtins. let simple_func = get_simple_function(self, name) .or_else(|| get_simple_function_f128(self, name)) .or_else(|| get_simple_function_f128_2args(self, name)); @@ -326,6 +331,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc ) } sym::ceilf16 + | sym::copysignf16 | sym::floorf16 | sym::fmaf16 | sym::maxnumf16 @@ -441,7 +447,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc match int_type_width_signed(args[0].layout.ty, self) { Some((width, signed)) => match name { sym::ctlz | sym::cttz => { - let func = self.current_func.borrow().expect("func"); + let func = self.current_func(); let then_block = func.new_block("then"); let else_block = func.new_block("else"); let after_block = func.new_block("after"); @@ -1109,7 +1115,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // for (int counter = 0; value != 0; counter++) { // value &= value - 1; // } - let func = self.current_func.borrow().expect("func"); + let func = self.current_func(); let loop_head = func.new_block("head"); let loop_body = func.new_block("body"); let loop_tail = func.new_block("tail"); @@ -1188,7 +1194,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let result_type = lhs.get_type(); if signed { // Based on algorithm from: https://stackoverflow.com/a/56531252/389119 - let func = self.current_func.borrow().expect("func"); + let func = self.current_func(); let res = func.new_local(self.location, result_type, "saturating_sum"); let supports_native_type = self.is_native_int_type(result_type); let overflow = if supports_native_type { @@ -1259,7 +1265,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let result_type = lhs.get_type(); if signed { // Based on algorithm from: https://stackoverflow.com/a/56531252/389119 - let func = self.current_func.borrow().expect("func"); + let func = self.current_func(); let res = func.new_local(self.location, result_type, "saturating_diff"); let supports_native_type = self.is_native_int_type(result_type); let overflow = if supports_native_type { @@ -1483,10 +1489,9 @@ fn gen_fn<'a, 'gcc, 'tcx>( // FIXME(eddyb) find a nicer way to do this. cx.linkage.set(FunctionType::Internal); let func = cx.declare_fn(name, fn_abi); - let func_val = unsafe { std::mem::transmute::<Function<'gcc>, RValue<'gcc>>(func) }; - cx.set_frame_pointer_type(func_val); - cx.apply_target_cpu_attr(func_val); - let block = Builder::append_block(cx, func_val, "entry-block"); + cx.set_frame_pointer_type(func); + cx.apply_target_cpu_attr(func); + let block = Builder::append_block(cx, func, "entry-block"); let bx = Builder::build(cx, block); codegen(bx); (return_type, func) diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 6f6bc93b8b2..2e508813fc3 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -61,7 +61,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let (len, _) = args[1].layout.ty.simd_size_and_type(bx.tcx()); let expected_int_bits = (len.max(8) - 1).next_power_of_two(); - let expected_bytes = len / 8 + ((len % 8 > 0) as u64); + let expected_bytes = len / 8 + ((!len.is_multiple_of(8)) as u64); let mask_ty = args[0].layout.ty; let mut mask = match *mask_ty.kind() { @@ -676,7 +676,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let elem_type = vector_type.get_element_type(); let expected_int_bits = in_len.max(8); - let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64); + let expected_bytes = + expected_int_bits / 8 + ((!expected_int_bits.is_multiple_of(8)) as u64); // FIXME(antoyo): that's not going to work for masks bigger than 128 bits. let result_type = bx.type_ix(expected_int_bits); @@ -779,6 +780,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( sym::simd_fsin => "sin", sym::simd_fsqrt => "sqrt", sym::simd_round => "round", + sym::simd_round_ties_even => "rint", sym::simd_trunc => "trunc", _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }), }; @@ -826,6 +828,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( | sym::simd_fsin | sym::simd_fsqrt | sym::simd_round + | sym::simd_round_ties_even | sym::simd_trunc ) { return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args); diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt index d931f0d3b5e..544d0bfc710 100644 --- a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt +++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt @@ -9,6 +9,7 @@ tests/ui/iterators/iter-sum-overflow-debug.rs tests/ui/iterators/iter-sum-overflow-overflow-checks.rs tests/ui/mir/mir_drop_order.rs tests/ui/mir/mir_let_chains_drop_order.rs +tests/ui/mir/mir_match_guard_let_chains_drop_order.rs tests/ui/oom_unwind.rs tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs tests/ui/panic-runtime/abort.rs diff --git a/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py b/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py index ed0ebf00719..88927f39b93 100644 --- a/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py +++ b/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py @@ -176,14 +176,14 @@ def update_intrinsics(llvm_path, llvmint, llvmint2): out.write("// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py`\n") out.write("// DO NOT EDIT IT!\n") out.write("/// Translate a given LLVM intrinsic name to an equivalent GCC one.\n") - out.write("fn map_arch_intrinsic(name:&str)->&str{\n") - out.write('let Some(name) = name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", name) };\n') + out.write("fn map_arch_intrinsic(full_name:&str)->&'static str{\n") + out.write('let Some(name) = full_name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) };\n') out.write('let Some((arch, name)) = name.split_once(\'.\') else { unimplemented!("***** unsupported LLVM intrinsic {}", name) };\n') out.write("match arch {\n") for arch in archs: if len(intrinsics[arch]) == 0: continue - out.write("\"{}\" => {{ #[allow(non_snake_case)] fn {}(name: &str) -> &str {{ match name {{".format(arch,arch)) + out.write("\"{}\" => {{ #[allow(non_snake_case)] fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch,arch)) intrinsics[arch].sort(key=lambda x: (x[0], x[2])) out.write(' // {}\n'.format(arch)) for entry in intrinsics[arch]: @@ -196,9 +196,9 @@ def update_intrinsics(llvm_path, llvmint, llvmint2): out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1])) else: out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1])) - out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {}", name),\n') - out.write("}} }} {}(name) }}\n,".format(arch)) - out.write(' _ => unimplemented!("***** unsupported LLVM architecture {}", name),\n') + out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n') + out.write("}} }} {}(name,full_name) }}\n,".format(arch)) + out.write(' _ => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic:{full_name}"),\n') out.write("}\n}") subprocess.call(["rustfmt", output_file]) print("Done!") |
